Java线程概述及API1
1 创建线程与创建线程运行时代码
在Java中,创建线程的方式只有一种,就是创建Thread对象的实例。创建线程运行时代码
有三种方式:
第一种:继承Thread
类,覆写其run
方法。
第二种:实现Runnable
接口,实现run
方法,Thread类也实现了Runable接口。
第三种:实现Callable
接口,实现其call
方法,这种方式是在JDK1.5中的java并发包中引入的。
2 start()方法与run()方法的区别
start
()方法用于启动线程,start方法调用之后,线程进入可运行状态,一旦线程调度程序调度执行,线程即进入运行状态,线程启动后JVM才会给线程分配相应的资源,例如栈内存空间。然后回调线程运行时代码。
run
()方法用于执行线程的运行时代码,如果直接调用该方法并没有创建新的线程而是在当前线程中被执行。
3 覆盖了Thread对象的run方法,同时传入一个Runnable的实现类?
我们知道线程创建完成之后,然后JVM回调线程运行时代码run(),
所以查看Thread的默认run()
实现:
/* What will be run. */ private Runnable target; .... @Override public void run() { if (target != null) { target.run(); } }
其中target就是Runable对象,默认的run方法的逻辑是,如果传递了Runnable的实现类,就运行Runnable的run方法。故:当覆盖了Thread对象的run方法之后,执行的肯定是覆盖之后的逻辑,原来的这段逻辑如果不存在了,
就算传入了Runnable的实现类,也不会执行。
4 sleep()方法与wait()方法的区别
sleep()方法是Thread类中定义的方法,可以在任意地方调用,作用是让线程进行休眠暂停执行,在休眠期间线程不会请求CPU执行,因此其他线程(甚至更低优先级的线程)可以获得更多的运行机会。但是如果持有同步锁,并不会释放锁。
sleep方法有InterruptedException编译时异常需要捕获。它是静态方法,所以不能指定休眠某一特定的线程t.sleep(),它只会是使当前线程被sleep 而不是t线程。sleep方法调用之后,线程进入到阻塞状态并不释放所占有的资源,sleep方法结束返回之后,线程重新回到可运行状态,而不是运行状态,需要线程调度机制重新恢复其到运行状态。
wait()方法是Object类中定义的方法,只能在同步方法或者同步代码块中调用,如果持有同步锁,会释放锁,让其他需要获得该锁的线程有机会运行。当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同)
wait方法同样也可以在wait期间因为被其他对象调用interrupt()方法二产生InterruptedException运行时异常。一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程。调用wait或者notify的时候,当前线程必须要是对象lock的拥有者,否则会抛出IllegalMonitorStateException异常。
synchronized (share) { share.wait(); }
当线程在synchronized中调用了share.wait()时,在放弃了CPU的同时,也放弃了share这个对象的lock,进入这个对象的wait pool。
当另外一个线程调用了share.notify()时,将从wait pool中拿出一个线程,让该线程获得lock,并进入可运行状态,等待线程调度执行。
这也就是为什么wait/notify需要加锁的原因。