首先提出两个问题,带着这两个问题往下看:
1.真正实现多线程,因为我自己刚开始学java的多线程时只知道,多线程是执行线程类的run方法,所以就在代码中手动调用了run方法,但实际上这么做是无效的。所以这里也简单写一下,算是给同样是初学者们的小提醒。
2.实现线程间的资源共享
java中实现多线程有两种方法:
1.继承Thread类
2.实现Runnable接口
对于第一种方法、继承Thread类:
首先我们知道,多线程就是执行线程类的run()方法,所以这里我们复写了线程类的run()方法,然后调用之。
class MyThread extends Thread{ int t = 10; String name = ""; MyThread(String name){ super(name); this.name = name; } public void run(){ while(t > 0){ System.out.println(name + ":" + t--); } } } class s1{ public static void main(String args[]){ MyThread m1 = new MyThread("m1"); MyThread m2 = new MyThread("m2"); m1.run(); m2.run(); } }
输出结果:
m1:10 m1:9 m1:8 m1:7 m1:6 m1:5 m1:4 m1:3 m1:2 m1:1 m2:10 m2:9 m2:8 m2:7 m2:6 m2:5 m2:4 m2:3 m2:2 m2:1
从运行结果不难可以看出,这些输出都是有规律可循的,并没有像想象中那样实现多线程。
这是因为:我们知道,一个线程实际运行的就是run方法里的代码。所以我们就直接调用了run方法,可是还有一点我们没有注意的,就是多线程需要有操作系统的支持。
Thread类中定义的start方法中,调用了一个private native void start0()方法,这里的native表明,这个方法是本地方法,可以与底层操作系统交互,来开启操作系统的多线程支持。这就是JNI(Java Native Interface)java本地接口。所以单纯的调用run方法是不行的,要调用start方法才能真正的开启多线程。
上面的代码修22、23行改为:
m1.start();
m2.start();
到这里我们的第1个问题也得到了解答。
至于第二种方法,实现runnable接口的类声明与之前大同小异,只是在主函数中有所不同:
不同在于,一个实现runnable接口的类没有start方法,这就无法开启线程,不过别急,看看Thread类,他有一个构造方法public Thread(Runnable targer)。所以可以再代码中这样写:
//这里假设 MyThread 类是一个实现了runnable接口的类 MyThread my = new MyThread(); new Thread(my).start;
这样就可以通过一个Thread实例来间接开启一个线程。
好了 现在我们来看看第二个问题,资源共享。最经典的就是买票问题:
class MyThread implements Runnable{ private static int ticket=10; public void run(){ while(ticket>0){ System.out.println(Thread.currentThread().getName()+':'+ticket--); } } } public class TestThread{ public static void main(String[] args){ MyThread mt=new MyThread(); new Thread(mt).start(); new Thread(mt).start(); new Thread(mt).start(); new Thread(mt).start(); } }
这样执行出来的就是三个线程同时操作一个数据,就像三个窗口在同时卖一趟火车票,一共有10张。