版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第Java基础之多线程方法状态和创建方法目录Java之线程的五大状态及其常用方法(六个状态还有timed_wating超时等待)1.线程的五大状态及其转换
2.设置或获取多线程的线程名称的方法
3.线程休眠------sleep()方法
4.线程让步------yield()方法
5.等待线程终止------join()方法
6.线程停止
7.线程等待------wait()方法
8.线程唤醒-------notify()方法
9.notifyAll()方法
JAVA多线程有哪几种实现方式?
1.继承Thread类
2.实现Runnable接口
3.使用Callable和FutureTask创建线程
4.通过线程池创建线程(使用ExecutorService、Callable、Future实现有返回结果的多线程。)
总结
Java之线程的五大状态及其常用方法(六个状态还有timed_wating超时等待)
1.线程的五大状态及其转换
线程的五大状态分别为:创建状态(New)、就绪状态(Runnable)、运行状态(Running)、阻塞状态(Blocked)、死亡状态(Dead)。
下面画出线程五大状态之间的关系图:
(1)新建状态:即单纯地创建一个线程,创建线程有三种方式,在我的博客:线程的创建,可以自行查看!
(2)就绪状态:在创建了线程之后,调用Thread类的start()方法来启动一个线程,即表示线程进入就绪状态!
(3)运行状态:当线程获得CPU时间,线程才从就绪状态进入到运行状态!
(4)阻塞状态:线程进入运行状态后,可能由于多种原因让线程进入阻塞状态,如:调用sleep()方法让线程睡眠,调用wait()方法让线程等待,调用join()方法、suspend()方法(它现已被弃用!)以及阻塞式IO方法。
(5)死亡状态:run()方法的正常退出就让线程进入到死亡状态,还有当一个异常未被捕获而终止了run()方法的执行也将进入到死亡状态!
2.设置或获取多线程的线程名称的方法
由于在一个进程中可能有多个线程,而多线程的运行状态又是不确定的,即不知道在多线程中当前执行的线程是哪个线程,所以在多线程操作中需要有一个明确的标识符标识出当前线程对象的信息,这个信息往往通过线程的名称来描述。在Thread类中提供了一些设置或获取线程名称的方法:
(1)创建线程时设置线程名称:
publicThread(Runnabletarget,Stringname)
(2)设置线程名称的普通方法:
publicfinalsynchronizedvoidsetName(Stringname)
(3)取得线程名称的普通方法:
publicfinalStringgetName()
演示:
classMyThreadimplementsRunnable{
@Override
publicvoidrun(){
for(inti=0;ii++)
//currentThread()方法用于取得当前正在JVM中运行的线程
//使用getName()方法,用于获取线程的名称
System.out.println("当前线程:"+Thread.currentThread().getName()+"-----i="+i);
publicclassTest1{
publicstaticvoidmain(String[]args){
//创建线程对象thread1且没有设置线程名称
MyThreadmyThread1=newMyThread();
Threadthread1=newThread(myThread1);
thread1.start();
//创建线程对象thread2且使用setName设置线程名称
MyThreadmyThread2=newMyThread();
Threadthread2=newThread(myThread2);
thread2.setName("线程2");
thread2.start();
//创建线程对象thread3并在创建线程时设置线程名称
MyThreadmyThread3=newMyThread();
Threadthread3=newThread(myThread3,"线程3");
thread3.start();
输出:
当前线程:Thread-0-----i=0
当前线程:Thread-0-----i=1
当前线程:Thread-0-----i=2
当前线程:线程3-----i=0
当前线程:线程2-----i=0
当前线程:线程2-----i=1
当前线程:线程2-----i=2
当前线程:线程2-----i=3
当前线程:线程3-----i=1
当前线程:Thread-0-----i=3
当前线程:Thread-0-----i=4
当前线程:线程3-----i=2
当前线程:线程3-----i=3
当前线程:线程3-----i=4
当前线程:线程2-----i=4
通过上述代码及其运行结果可知:
(1)若没有手动设置线程名称时,会自动分配一个线程的名称,如线程对象thread1自动分配线程名称为Thread-0。
(2)多线程的运行状态是不确定的,不知道下一个要执行的是哪个线程,这是因为CPU以不确定方式或以随机的时间调用线程中的run()方法。
(3)需要注意的是,由于设置线程名称是为了区分当前正在执行的线程是哪一个线程,所以在设置线程名称时应避免重复!
3.线程休眠------sleep()方法
线程休眠:指的是让线程暂缓执行,等到预计时间之后再恢复执行。
(1)线程休眠会交出CPU,让CPU去执行其他的任务。
(2)调用sleep()方法让线程进入休眠状态后,sleep()方法并不会释放锁,即当前线程持有某个对象锁时,即使调用sleep()方法其他线程也无法访问这个对象。
(3)调用sleep()方法让线程从运行状态转换为阻塞状态;sleep()方法调用结束后,线程从阻塞状态转换为可执行状态。
sleep()方法:
publicstaticnativevoidsleep(longmillis)throwsInterruptedException;
从上面方法参数中可以看出sleep()方法的休眠时间是以毫秒作为单位。
关于sleep()方法的操作如下:
classMyThreadimplementsRunnable{
@Override
publicvoidrun(){
for(inti=0;ii++)
//使用Thread类的sleep()方法,让线程处于休眠状态
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
System.out.println("当前线程:"+Thread.currentThread().getName()+"-----i="+i);
publicclassTest1{
publicstaticvoidmain(String[]args){
MyThreadmyThread=newMyThread();
//利用myThread对象分别创建三个线程
Threadthread1=newThread(myThread);
thread1.start();
Threadthread2=newThread(myThread);
thread2.start();
Threadthread3=newThread(myThread);
thread3.start();
某次运行结果如下所示:
当前线程:Thread-2-----i=0
当前线程:Thread-1-----i=0
当前线程:Thread-0-----i=0
当前线程:Thread-2-----i=1
当前线程:Thread-0-----i=1
当前线程:Thread-1-----i=1
当前线程:Thread-2-----i=2
当前线程:Thread-1-----i=2
当前线程:Thread-0-----i=2
当前线程:Thread-2-----i=3
当前线程:Thread-1-----i=3
当前线程:Thread-0-----i=3
当前线程:Thread-2-----i=4
当前线程:Thread-0-----i=4
当前线程:Thread-1-----i=4
注:
(1)通过运行代码进行观察,发现运行结果会等待一段时间,这就是sleep()方法让原本处于运行状态的线程进入了休眠,从而进程的状态从运行状态转换为阻塞状态。
(2)以上代码创建的三个线程肉眼观察,发现它们好像是同时进入休眠状态,但其实并不是同时休眠的。
4.线程让步------yield()方法
线程让步:暂停当前正在执行的线程对象,并执行其他线程。
(1)调用yield()方法让当前线程交出CPU权限,让CPU去执行其他线程。
(2)yield()方法和sleep()方法类似,不会释放锁,但yield()方法不能控制具体交出CPU的时间。
(3)yield()方法只能让拥有相同优先级的线程获取CPU执行的机会。
(4)使用yield()方法不会让线程进入阻塞状态,而是让线程从运行状态转换为就绪状态,只需要等待重新获取CPU执行的机会。
yield()方法:
publicstaticnativevoidyield();
关于yield()方法的操作如下:
classMyThreadimplementsRunnable{
@Override
publicvoidrun(){
for(inti=0;ii++)
//使用Thread类的yield()方法
Thread.yield();
System.out.println("当前线程:"+Thread.currentThread().getName()+"-----i="+i);
publicclassTest1{
publicstaticvoidmain(String[]args){
MyThreadmyThread=newMyThread();
//利用myThread对象分别创建三个线程
Threadthread1=newThread(myThread);
thread1.start();
Threadthread2=newThread(myThread);
thread2.start();
Threadthread3=newThread(myThread);
thread3.start();
某次运行结果如下所示:
当前线程:Thread-0-----i=0
当前线程:Thread-0-----i=1
当前线程:Thread-0-----i=2
当前线程:Thread-0-----i=3
当前线程:Thread-0-----i=4
当前线程:Thread-1-----i=0
当前线程:Thread-2-----i=0
当前线程:Thread-2-----i=1
当前线程:Thread-2-----i=2
当前线程:Thread-2-----i=3
当前线程:Thread-2-----i=4
当前线程:Thread-1-----i=1
当前线程:Thread-1-----i=2
当前线程:Thread-1-----i=3
当前线程:Thread-1-----i=4
5.等待线程终止------join()方法
等待线程终止:指的是如果在主线程中调用该方法时就会让主线程休眠,让调用join()方法的线程先执行完毕后再开始执行主线程。
join()方法:
publicfinalvoidjoin()throwsInterruptedException{
join(0);
注:上面的join()方法是不带参数的,但join()方法还可以带参数,下去自行了解!
关于join()方法的操作如下:
classMyThreadimplementsRunnable{
@Override
publicvoidrun(){
for(inti=0;ii++)
//使用Thread类的sleep()方法
try{
Thread.sleep(3000);
}catch(InterruptedExceptione){
e.printStackTrace();
System.out.println("当前线程:"+Thread.currentThread().getName()+"-----i="+i);
publicclassTest1{
publicstaticvoidmain(String[]args)throwsInterruptedException{
MyThreadmyThread=newMyThread();
Threadthread1=newThread(myThread,"自己创建的线程");
thread1.start();
System.out.println("主线程:"+Thread.currentThread().getName());
//线程对象thread1调用join()方法
thread1.join();
System.out.println("代码结束");
运行结果如下所示:
主线程:main
当前线程:自己创建的线程-----i=0
当前线程:自己创建的线程-----i=1
代码结束
若不调用join()方法的话,运行结果如下所示:
主线程:main
代码结束
当前线程:自己创建的线程-----i=0
当前线程:自己创建的线程-----i=1
故通过两个运行结果可以更加深刻地感受到调用join()方法后的作用!调用join()方法和不调用join()方法的区别!
6.线程停止
多线程中停止线程有三种方式:
(1)设置标记位,让线程正常停止。
classMyThreadimplementsRunnable{
//设置标记位
privatebooleanflag=true;
publicvoidsetFlag(booleanflag){
this.flag=flag;
@Override
publicvoidrun(){
inti=0;
while(flag)
System.out.println("第"+(i++)+"次执行-----"+"线程名称:"+Thread.currentThread().getName());
publicclassTest1{
publicstaticvoidmain(String[]args)throwsInterruptedException{
MyThreadmyThread=newMyThread();
Threadthread1=newThread(myThread,"自己创建的线程");
thread1.start();
//让主线程sleep一毫秒
Thread.sleep(1);
//修改标记位的值,让自己创建的线程停止
myThread.setFlag(false);
System.out.println("代码结束");
运行结果如下所示:
第0次执行-----线程名称:自己创建的线程
第1次执行-----线程名称:自己创建的线程
第2次执行-----线程名称:自己创建的线程
第3次执行-----线程名称:自己创建的线程
第4次执行-----线程名称:自己创建的线程
第5次执行-----线程名称:自己创..............
第19次执行-----线程名称:自己创建的线程
第20次执行-----线程名称:自己创建的线程
第21次执行-----线程名称:自己创建的线程
第22次执行-----线程名称:自己创建的线程
第23次执行-----线程名称:自己创建的线程
第24次执行-----线程名称:自己创建的线程
第25次执行-----线程名称:自己创建的线程
第26次执行-----线程名称:自己创建的线程
代码结束
(2)使用stop()方法强制使线程退出,但是使用该方法不安全,已经被废弃了!
classMyThreadimplementsRunnable{
@Override
publicvoidrun(){
for(inti=0;ii++)
System.out.println("线程名称:"+Thread.currentThread().getName()+"------i="+i);
publicclassTest1{
publicstaticvoidmain(String[]args)throwsInterruptedException{
MyThreadmyThread=newMyThread();
Threadthread1=newThread(myThread,"自己创建的线程");
thread1.start();
//让主线程sleep一毫秒
Thread.sleep(1);
//调用已被弃用的stop()方法去强制让线程退出
thread1.stop();
System.out.println("代码结束");
某次运行结果如下所示:
线程名称:自己创建的线程------i=0
线程名称:自己创建的线程------i=1
线程名称:自己创建的线程------i=2
线程名称:自己创建的线程------i=3
线程名称:自己创建的线程------i=4
线程名称:自己创建的线程------i=5
线程名称:自己创建的线程------i=6
......
线程名称:自己创建的线程------i=28
线程名称:自己创建的线程------i=29
线程名称:自己创建的线程------i=30
线程名称:自己创建的线程------i=31
线程名称:自己创建的线程------i=48
线程名称:自己创建的线程------i=49
线程名称:自己创建的线程------i=50
线程名称:自己创建的线程------i=51线程名称:自己创建的线程------i=51代码结束
从上述代码和运行结果可以看出,原本线程对象thread1的run()方法中应该执行100次语句“System.out.println(“线程名称:”+Thread.currentThread().getName()+"------i="+i);”,但现在没有执行够100次,所以说stop()方法起到了让线程终止的作用。再从运行结果上可以看出,i=51被执行了两次且没有换行,这就体现了调用stop()方法的不安全性!
下面正式地解释stop()方法为什么不安全?
因为stop()方法会解除由线程获得的所有锁,当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程会立即停止,假如一个线程正在执行同步方法:
publicsynchronizedvoidfun(){
x=3;
y=4;
由于方法是同步的,多线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x=3;时,被调用的stop()方法使得线程即使在同步方法中也要停止,这就造成了数据的不完整性。故,stop()方法不安全,已经被废弃,不建议使用!
(3)使用Thread类的interrupt()方法中断线程。
classMyThreadimplementsRunnable{
@Override
publicvoidrun(){
inti=0;
while(true)
//使用sleep()方法,使得线程由运行状态转换为阻塞状态
try{
Thread.sleep(1000);
//调用isInterrupted()方法,用于判断当前线程是否被中断
booleanbool=Thread.currentThread().isInterrupted();
if(bool){
System.out.println("非阻塞状态下执行该操作,当前线程被中断!");
break;
System.out.println("第"+(i++)+"次执行"+"线程名称:"+Thread.currentThread().getName());
}catch(InterruptedExceptione){
System.out.println("退出了!");
//这里退出了阻塞状态,且中断标志bool被系统自动清除设置为false,所以此处的bool为false
booleanbool=Thread.currentThread().isInterrupted();
System.out.println(bool);
//退出run()方法,中断进程
return;
publicclassTest1{
publicstaticvoidmain(String[]args)throwsInterruptedException{
MyThreadmyThread=newMyThread();
Threadthread1=newThread(myThread,"自己创建的线程");
thread1.start();
//让主线程sleep三秒
Thread.sleep(3000);
//调用interrupt()方法
errupt();
System.out.println("代码结束");
运行结果如下所示:
第0次执行线程名称:自己创建的线程
第1次执行线程名称:自己创建的线程
第2次执行线程名称:自己创建的线程
代码结束
退出了!
false
(1)interrupt()方法只是改变中断状态而已,它不会中断一个正在运行的线程。具体来说就是,调用interrupt()方法只会给线程设置一个为true的中断标志,而设置之后,则根据线程当前状态进行不同的后续操作。
(2)如果线程的当前状态出于非阻塞状态,那么仅仅将线程的中断标志设置为true而已;
(3)如果线程的当前状态出于阻塞状态,那么将在中断标志设置为true后,还会出现wait()、sleep()、join()方法之一引起的阻塞,那么会将线程的中断标志位重新设置为false,并抛出一个InterruptedException异常。
(4)如果在中断时,线程正处于非阻塞状态,则将中断标志修改为true,而在此基础上,一旦进入阻塞状态,则按照阻塞状态的情况来进行处理。例如,一个线程在运行状态时,其中断标志设置为true之后,一旦线程调用了wait()、sleep()、join()方法中的一种,立马抛出一个InterruptedException异常,且中断标志被程序自动清除,重新设置为false。
总结:调用Thread类的interrupted()方法,其本质只是设置该线程的中断标志,将中断标志设置为true,并根据线程状态决定是否抛出异常。因此,通过interrupted()方法真正实现线程的中断原理是:开发人员根据中断标志的具体值来决定如何退出线程。
7.线程等待------wait()方法
首先,wait()方法是Object类的方法,下面是无参的wait()方法:
publicfinalvoidwait()throwsInterruptedException{
wait(0);
(1)wait()方法的作用是让当前正在执行的线程进入线程阻塞状态的等待状态,该方法时用来将当前线程置入“预执行队列”中,并且调用wait()方法后,该线程在wait()方法所在的代码处停止执行,直到接到一些通知或被中断为止。
(2)wait()方法只能在同步代码块或同步方法中调用,故如果调用wait()方法时没有持有适当的锁时,就会抛出异常。
(3)wait()方法执行后,当前线程释放锁并且与其他线程相互竞争重新获得锁。
下面调用wait()方法:
publicclassTest1{
publicstaticvoidmain(String[]args){
Objectobject=newObject();
synchronized(object){
System.out.println("调用wait()前");
//调用Object类的wait()方法
try{
object.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
System.out.println("调用wait()后");
运行结果如下所示:
调用wait()前
解析:此时,程序依然处于执行状态。原本应该打印两条语句:调用wait()前调用wait()后,但是由于该程序还没有运行完而且只打印了一条语句:调用wait()前。这是因为什么呢?因为调用了Object类的wait()方法,使得程序在执行wait()方法之后一直等待下去,故只执行了调用wait()方法前的语句。但程序不能这样一直等待下去,这个时候就需要另一个方法去唤醒调用wait()方法的处于等待状态的线程,让等待线程继续执行下去,该方法为notify()方法。
8.线程唤醒-------notify()方法
首先,notify()方法也是Object类的方法:
publicfinalnativevoidnotify();
(1)notify()方法要在同步代码块或同步方法中调用。
(2)notify()方法是用来通知那些等待该对象的对象锁的线程,对其调用wait()方法的对象发出通知让这些线程不再等待,继续执行。
(3)如果有多个线程都在等待,则由线程规划器随机挑选出一个呈wait状态的线程将其线程唤醒,继续执行该线程。
(4)调用notify()方法后,当前线程并不会马上释放该对象锁,要等到执行notify()方法的线程执行完才会释放对象锁。
下面调用notify()方法:
classMyThreadimplementsRunnable{
privatebooleanflag;
privateObjectobject;
//定义一个构造方法
publicMyThread(booleanflag,Objectobject){
this.flag=flag;
this.object=object;
//定义一个普通方法,其中调用了wait()方法
publicvoidwaitThread(){
synchronized(this.object){
try{
System.out.println("调用wait()前------"+Thread.currentThread().getName());
//调用wait()方法
this.object.wait();
System.out.println("调用wait()后------"+Thread.currentThread().getName());
}catch(InterruptedExceptione){
e.printStackTrace();
//定义一个普通方法,其中调用了notify()方法
publicvoidnotifyThread(){
synchronized(this.object){
try{
System.out.println("调用notify前------"+Thread.currentThread().getName());
//调用notify()方法
this.object.notify();
System.out.println("调用notify()后------"+Thread.currentThread().getName());
}catch(Exceptione){
e.printStackTrace();
@Override
publicvoidrun(){
if(this.flag){
this.waitThread();
}else{
this.notifyThread();
publicclassTest1{
publicstaticvoidmain(String[]args){
Objectobject=newObject();
//实例化调用wait()的线程
MyThreadwait=newMyThread(true,object);
ThreadwaitThread=newThread(wait,"wait线程");
//实例化调用notify()的线程
MyThreadnotify=newMyThread(false,object);
ThreadnotifyThread=newThread(notify,"notify线程");
//启动线程
waitThread.start();
//调用一下sleep()方法,使得查看效果更明显
try{
Thread.sleep(2000);
}catch(InterruptedExceptione){
e.printStackTrace();
notifyThread.start();
运行结果
调用wait()前------wait线程
调用notify前------notify线程
调用notify()后------notify线程
调用wait()后------wait线程
解析:根据run方法及实例化的线程对象,wait线程执行了waitThread()方法,该方法中调用了wait()方法使得线程进入线程阻塞状态的等待状态并释放锁,如果没有其他线程去唤醒该线程的话wait线程将一直等待下去。此时,notify线程执行了notifyThread()方法,该方法中调用了notify()方法,使得notify线程去唤醒wait线程,让wait线程不再等待下去,并且先将notify线程执行完后释放锁再执行wait线程的wait()方法之后的语句。所以打印如上所示。
但要注意的是,当有多个线程处于等待时,调用notify()方法唤醒线程时,就会依然有线程处于等待状态,演示如下:
classMyThreadimplementsRunnable{
privatebooleanflag;
privateObjectobject;
//定义一个构造方法
publicMyThread(booleanflag,Objectobject){
this.flag=flag;
this.object=object;
//定义一个普通方法,其中调用了wait()方法
publicvoidwaitThread(){
synchronized(this.object){
try{
System.out.println("调用wait()前------"+Thread.currentThread().getName());
//调用wait()方法
this.object.wait();
System.out.println("调用wait()后------"+Thread.currentThread().getName());
}catch(InterruptedExceptione){
e.printStackTrace();
//定义一个普通方法,其中调用了notify()方法
publicvoidnotifyThread(){
synchronized(this.object){
try{
System.out.println("调用notify前------"+Thread.currentThread().getName());
//调用notify()方法
this.object.notify();
System.out.println("调用notify()后------"+Thread.currentThread().getName());
}catch(Exceptione){
e.printStackTrace();
@Override
publicvoidrun(){
if(this.flag){
this.waitThread();
}else{
this.notifyThread();
publicclassTest1{
publicstaticvoidmain(String[]args){
Objectobject=newObject();
//实例化调用wait()的线程
MyThreadwait=newMyThread(true,object);
ThreadwaitThread1=newThread(wait,"wait线程1");
ThreadwaitThread2=newThread(wait,"wait线程2");
ThreadwaitThread3=newThread(wait,"wait线程3");
//实例化调用notify()的线程
MyThreadnotify=newMyThread(false,object);
ThreadnotifyThread=newThread(notify,"notify线程");
//启动3个等待线程
waitThread1.start();
waitThread2.start();
waitThread3.start();
//调用一下sleep()方法,使得查看效果更明显
try{
Thread.sleep(2000);
}catch(InterruptedExceptione){
e.printStackTrace();
notifyThread.start();
运行结果如下所示:
调用wait()前------wait线程1
调用wait()前------wait线程3
调用wait()前------wait线程2
调用notify前------notify线程
调用notify()后------notify线程
调用wait()后------wait线程1
此时程序并没有执行完毕,因为依然有线程处于等待状态,所以notify()只是随机将某一个等待线程唤醒,并没有唤醒所有等待线程。那么,若有多个线程处于等待状态时,如何将所有等待线程都唤醒呢?下面将介绍notifyAll()方法
9.notifyAll()方法
Object类的notifyAll()方法:
publicfinalnativevoidnotifyAll();
notifyAll()方法将同一对象锁的所有等待线程全部唤醒。代码演示如下:
classMyThreadimplementsRunnable{
privatebooleanflag;
privateObjectobject;
//定义一个构造方法
publicMyThread(booleanflag,Objectobject){
this.flag=flag;
this.object=object;
//定义一个普通方法,其中调用了wait()方法
publicvoidwaitThread(){
synchronized(this.object){
try{
System.out.println("调用wait()前------"+Thread.currentThread().getName());
//调用wait()方法
this.object.wait();
System.out.println("调用wait()后------"+Thread.currentThread().getName());
}catch(InterruptedExceptione){
e.printStackTrace();
//定义一个普通方法,其中调用了notifyAll()方法
publicvoidnotifyThread(){
synchronized(this.object){
try{
System.out.println("调用notify前------"+Thread.currentThread().getName());
//调用notifyAll()方法
this.object.notifyAll();
System.out.println("调用notify()后------"+Thread.currentThread().getName());
}catch(Exceptione){
e.printStackTrace();
@Override
publicvoidrun(){
if(this.flag){
this.waitThread();
}else{
this.notifyThread();
publicclassTest1{
publicstaticvoidmain(String[]args){
Objectobject=newObject();
//实例化调用wait()的线程
MyThreadwait=newMyThread(true,object);
ThreadwaitThread1=newThread(wait,"wait线程1");
ThreadwaitThread2=newThread(wait,"wait线程2");
ThreadwaitThread3=newThread(wait,"wait线程3");
//实例化调用notifyAll()的线程
MyThreadnotify=newMyThread(false,object);
ThreadnotifyThread=newThread(notify,"notify线程");
//启动3个等待线程
waitThread1.start();
waitThread2.start();
waitThread3.start();
//调用一下sleep()方法,使得查看效果更明显
try{
Thread.sleep(2000);
}catch(InterruptedExceptione){
e.printStackTrace();
notifyThread.start();
运行结果如下所示:
调用wait()前------wait线程1
调用wait()前------wait线程2
调用wait()前------wait线程3
调用notify前------notify线程
调用notify()后------notify线程
调用wait()后------wait线程3
调用wait()后------wait线程2
调用wait()后------wait线程1
解析:此时,程序执行完毕,所有等待线程都被调用notifyAll()方法的具有同一对象锁的线程唤醒,故每一个等待线程都会在调用wait()后继续执行直到该线程结束。
JAVA多线程有哪几种实现方式?
1.继承Thread类
1)定义Thread类的子类,并重写Thread类的run()方法。
2)创建Thread子类的实例,及创建了线程对象。
3)调用线程对象的start()方法来启动该线程。
classMyThreadextendsThread{
publicvoidrun(){
System.out.println("线程运行");
publicclassTest{
publicstaticvoidmain(String[]args){
MyThreadthread=newMyThread();
thread.start();//开启线程
Thread类常用方法
Thread.currentThread():是Thread类的静态方法,该方法总是返回当前正在执行的线程对象。
StringgetName():该方法是Thread类的实例方法,是返回调用该方法的线程名字。
2.实现Runnable接口
1)定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法同样是线程执行体。
2)创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
3)调用线程对象的start()方法来启动该线程。
classRunnaimplementsRunnable
publicvoidrun(){
System.out.println("线程运行");
publicclassTest{
publicstaticvoidmain(String[]args){
Runnarunna=newRunna();
Threadt=newThread(runna);
t.start();//开启线程
推荐使用那种:很明显,我们在使用继承Thread方式时,有一个很大的缺点,就是我们继承了Thread后就不能继承其他类了。但是如果我们实现Runnable的话,恰好可以解决这个问题。
一个类只能extends一个父类,但可以implements多个接口。
一个接口则可以同时extends多个接口,却不能implements任何接口。
3.使用Callable和FutureTask创建线程
1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值。
2)创建Callable实
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GMP合规专员培训大纲
- 2025年宠物食品配方设计师培训试题及答案
- 2026年浙江电信校园招聘考试备考试题及答案解析
- 2026福建福州冶城发展集团有限公司招聘6人考试参考试题及答案解析
- 2026中国药科大学继续教育学院工作人员招聘2人考试参考试题及答案解析
- 2026年石家庄炼化校园招聘考试备考题库及答案解析
- 2026内蒙古锡林郭勒盟残疾人辅助性就业服务中心招聘26人考试参考题库及答案解析
- 2026年西南证券股份有限公司校园招聘笔试模拟试题及答案解析
- 2026年枣庄市妇幼保健院第一批急需紧缺人才引进(10名)考试参考试题及答案解析
- 2026广东华南理工大学电力学院张俊勃教授科研团队招聘科研助理1人考试参考题库及答案解析
- 周杰伦课件介绍
- 公司管理层离职管理制度
- 2025年重庆市中考数学试卷真题及答案详解(精校打印版)
- (高清版)DG∕TJ 08-110-2021 餐饮单位清洁设计技术标准
- 年产200吨高纯金属铯铷项目报告书
- 煤矿各级各岗位人员职业病防治责任制
- 2025新人教版七年级下册英语 Unit 2知识点梳理及语法讲义(答案版)
- (新版)多旋翼无人机超视距驾驶员执照参考试题(附答案)
- 2025年包钢(集团)公司招聘笔试参考题库含答案解析
- 【公开课】多姿与多彩(生活色彩)课件高中美术人教版+(2019)+选择性必修1+绘画
- 《植物生产与环境》考试复习题及答案
评论
0/150
提交评论