标签:
------Java EE培训、Android培训、iOS培训、期待与您交流! -------
进程:正在执行的应用程序。一个应用程序运行时内存分配的空间。
线程:进程中一个程序执行的控制单元,一条执行路径。负责程序的执行顺序。
多线程:在java虚拟机启动的时候会有一个java.exe的执行程序,即一个进程。该进程中至少有一个线程负责java程序的运行。而且这个线程运行的代码存在于main方法中。
class Demo extends Thread { public void run() { for (int i=0;i<60 ;i++ ) { System.out.println("demo--"+i); } } } class ThreadTest { public static void main(String[] args) { Demo d = new Demo(); Thread t =new Thread(d); d.start(); for (int i=0;i<60 ;i++ ) { System.out.println("main-------"+i); } } }
运行后发现每一次结果都不同,因为多个线程都获取cpu的执行权。cpu执行到谁,谁就运行。至于执行多久,cpu说的算。 这就是多线程的特性之一:cpu每次只执行一个程序,只是在快速的不同线程间切换,表现了多线程的随机性
又如:
class ThreadTest { public static void main(String[] args) { Demo d1 = new Demo("one"); Demo d2 = new Demo("two"); //d1.start(); //d2.start(); d1.run(); d2.run(); } }
使用run方法,d2必须等到d1执行完才会执行自己的代码(等于没有运行线程)。而使用start,相当于同时开启了两个独立的控制单元,已达到同时运行的目的,提高了效率。
示例: 模拟火车站四个售票窗口同时开通售票、票数20张、预计全部售完的情况。
第一种创建线程的方式
class Mlpc extends Thread //第一步、定义类继承Thread类
{
private int ticket = 20;
public void run() //第二步、覆写run方法,把需要被现场运行的代码都写在其中
{
while(true)
{
if(ticket>0)
{
System.out.println(Thread.currentThread()+" "+ticket--);
}
}
}
}
class mlpcDemo
{
public static void main(String[] args)
{
Mlpc m1 = new Mlpc();//第三步、通过创建Thread类的子类对象,创建了线程对象。
Mlpc m2 = new Mlpc();
Mlpc m3 = new Mlpc();
Mlpc m4 = new Mlpc();
m1.start();//第四步、调用start方法,开启线程,执行run方法
m1.start();
m1.start();
m1.start();
}
}
很明显,结果会出现四条线程‘各自为营’,各卖20张票的情况。
以上结果肯定不符合要求,于是我们使用第二种创建线程的方式。
class Mlpc implements Runnable//第一步、定义类实现Runnable接口
{
private int ticket = 20;
public void run() //第二步、覆盖接口run方法,封装线程要运行的代码
{
while(true)
{
if(ticket>0)
{
System.out.println(Thread.currentThread()+" "+ticket--);
}
}
}
}
class mlpcDemo
{
public static void main(String[] args)
{
Mlpc m = new Mlpc();
Thread th0 = new Thread(m);
Thread th1 = new Thread(m);
Thread th2 = new Thread(m);
Thread th3 = new Thread(m);
th0.start();
th1.start();
th2.start();
th3.start();
}
}
这样就对了。
run方法和 start方法
run方法 仅仅是对象调用方法,并没有运行线程 start方法 是开启线程并且执行线程中的run方法。
为什么要有Runnable介面的出现?
1:通过继承Thread类的方式,可以完成多线程的建立。但是这种方式有一个局限性,如果一个类已经有了自己的父类,就不可以继承Thread类,因为java单继承的局限性。
可是该类中的还有部分代码需要被多个线程同时执行。这时怎么办呢?
只有对该类进行额外的功能扩展,java就提供了一个介面Runnable。这个介面中定义了run方法,其实run方法的定义就是为了存储多线程要运行的代码。
所以,通常创建线程都用第二种方式。
因为实现Runnable介面可以避免单继承的局限性。
2:其实是将不同类中需要被多线程执行的代码进行抽取。将多线程要运行的代码的位置单独定义到介面中。为其他类进行功能扩展提供了前提。
所以Thread类在描述线程时,内部定义的run方法,也来自于Runnable介面。
实现Runnable介面可以避免单继承的局限性。而且,继承Thread,是可以对Thread类中的方法,进行子类复写的。但是不需要做这个复写动作的话,只为定义线程代码存放位置,实现Runnable介面更方便一些。所以Runnable介面将线程要执行的任务封装成了对象。
class ThreadTest { public static void main(String[] args) { ticket t = new ticket(); Thread t0 = new Thread(t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); t0.start(); t1.start(); t2.start(); t3.start(); } } class ticket implements Runnable { private int ticket = 100; public void run() { while(true) if(ticket>=0) System.out.println(ticket--); } }
标签:
原文地址:http://www.cnblogs.com/tozr/p/4148811.html