您好,欢迎访问三七文档
java中的多线程在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口。对于直接继承Thread的类来说,代码大致框架是:?123456789101112class类名extendsThread{方法1;方法2;…publicvoidrun(){//othercode…}属性1;属性2;…}先看一个简单的例子:?1234/***@authorRollen-Holt继承Thread类,直接调用run方法**/classhelloextendsThread{5678910111213141516171819202122232425262728publichello(){}publichello(Stringname){this.name=name;}publicvoidrun(){for(inti=0;i5;i++){System.out.println(name+运行+i);}}publicstaticvoidmain(String[]args){helloh1=newhello(A);helloh2=newhello(B);h1.run();h2.run();}privateStringname;}【运行结果】:A运行0A运行1A运行2A运行3A运行4B运行0B运行1B运行2B运行3B运行4我们会发现这些都是顺序执行的,说明我们的调用方法不对,应该调用的是start()方法。当我们把上面的主函数修改为如下所示的时候:?123456publicstaticvoidmain(String[]args){helloh1=newhello(A);helloh2=newhello(B);h1.start();h2.start();}然后运行程序,输出的可能的结果如下:A运行0B运行0B运行1B运行2B运行3B运行4A运行1A运行2A运行3A运行4因为需要用到CPU的资源,所以每次的运行结果基本是都不一样的,呵呵。注意:虽然我们在这里调用的是start()方法,但是实际上调用的还是run()方法的主体。那么:为什么我们不能直接调用run()方法呢?我的理解是:线程的运行需要本地操作系统的支持。如果你查看start的源代码的时候,会发现:?1234567891011121314publicsynchronizedvoidstart(){/***Thismethodisnotinvokedforthemainmethodthreadorsystem*groupthreadscreated/setupbytheVM.Anynewfunctionalityadded*tothismethodinthefuturemayhavetoalsobeaddedtotheVM.**AzerostatusvaluecorrespondstostateNEW.*/if(threadStatus!=0||this!=me)thrownewIllegalThreadStateException();group.add(this);start0();if(stopBeforeStart){151617stop0(throwableFromStop);}}privatenativevoidstart0();注意我用红色加粗的那一条语句,说明此处调用的是start0()。并且这个这个方法用了native关键字,次关键字表示调用本地操作系统的函数。因为多线程的实现需要本地操作系统的支持。但是start方法重复调用的话,会出现java.lang.IllegalThreadStateException异常。通过实现Runnable接口:大致框架是:?123456789101112class类名implementsRunnable{方法1;方法2;…publicvoidrun(){//othercode…}属性1;属性2;…}来先看一个小例子吧:?123456789101112131415161718192021/***@authorRollen-Holt实现Runnable接口**/classhelloimplementsRunnable{publichello(){}publichello(Stringname){this.name=name;}publicvoidrun(){for(inti=0;i5;i++){System.out.println(name+运行+i);}}publicstaticvoidmain(String[]args){helloh1=newhello(线程A);222324252627282930Threaddemo=newThread(h1);helloh2=newhello(线程B);Threaddemo1=newThread(h2);demo.start();demo1.start();}privateStringname;}【可能的运行结果】:线程A运行0线程B运行0线程B运行1线程B运行2线程B运行3线程B运行4线程A运行1线程A运行2线程A运行3线程A运行4关于选择继承Thread还是实现Runnable接口?其实Thread也是实现Runnable接口的:?12classThreadimplementsRunnable{//…345678publicvoidrun(){if(target!=null){target.run();}}}其实Thread中的run方法调用的是Runnable接口的run方法。不知道大家发现没有,Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式。关于代理模式,我曾经写过一个小例子呵呵,大家有兴趣的话可以看一下:和Runnable的区别:如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。?123456789101112/***@authorRollen-Holt继承Thread类,不能资源共享**/classhelloextendsThread{publicvoidrun(){for(inti=0;i7;i++){if(count0){System.out.println(count=+count--);}}}1314151617181920212223publicstaticvoidmain(String[]args){helloh1=newhello();helloh2=newhello();helloh3=newhello();h1.start();h2.start();h3.start();}privateintcount=5;}【运行结果】:count=5count=4count=3count=2count=1count=5count=4count=3count=2count=1count=5count=4count=3count=2count=1大家可以想象,如果这个是一个买票系统的话,如果count表示的是车票的数量的话,说明并没有实现资源的共享。我们换为Runnable接口?1234567891011121314151617classMyThreadimplementsRunnable{privateintticket=5;//5张票publicvoidrun(){for(inti=0;i=20;i++){if(this.ticket0){System.out.println(Thread.currentThread().getName()+正在卖票+this.ticket--);}}}}publicclasslzwCode{publicstaticvoidmain(String[]args){MyThreadmy=newMyThread();18192021newThread(my,1号窗口).start();newThread(my,2号窗口).start();newThread(my,3号窗口).start();}}【运行结果】:count=5count=4count=3count=2count=1总结一下吧:实现Runnable接口比继承Thread类所具有的优势:1):适合多个相同的程序代码的线程去处理同一个资源2):可以避免java中的单继承的限制3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。所以,本人建议大家劲量实现接口。?12/***@authorRollen-Holt3456789101112131415161718*取得线程的名称**/classhelloimplementsRunnable{publicvoidrun(){for(inti=0;i3;i++){System.out.println(Thread.currentThread().getName());}}publicstaticvoidmain(String[]args){hellohe=newhello();newThread(he,A).start();newThread(he,B).start();newThread(he).start();}}【运行结果】:AAABBBThread-0Thread-0Thread-0说明如果我们没有指定名字的话,系统自动提供名字。提醒一下大家:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。判断线程是否启动?12345678910111213141516/***@authorRollen-Holt判断线程是否启动**/classhelloimplementsRunnable{publicvoidrun(){for(inti=0;i3;i++){System.out.println(Thread.currentThread().getName());}}publicstaticvoidmain(String[]args){hellohe=newhello();Threaddemo=newThread(he);System.out.println(线程启动之前---》+demo.isAlive());demo.start();System.out.println(线程启动之后---》+demo.isAlive());1718}}【运行结果】线程启动之前---》false线程启动之后---》trueThread-0Thread-0Thread-0主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。线程的强制执行:?12345678910111213/***@authorRollen-Holt线程的强制执行**/classhelloimplementsRunnable{publicvoidrun(){for(inti=0;i3;i++){System.out.println(Thread.currentThread().getName());}}publicstaticvoidmain(String[]args){hellohe=newhello();14151617181920212223242526Threaddemo=newThread(he,线程);demo.start();for(inti=0;i50;++i){if(i10){try{demo.join();//强制执行demo}catch(Exceptione){e.printSt
本文标题:java中的多线程
链接地址:https://www.777doc.com/doc-6148768 .html