线程中状态
和进程意义。线程从启动到终止一种由5个状态。分别时创建状态,就绪状态,运行状态,阻塞状态和终止状态。
状态转换常用方法
创建状态->(start()方法)->就绪状态
就绪状态->(系统调度)->运行状态
运行状态->(yiekd()方法)->运行状态
运行状态->(sleep()\join()\wait()方法)->阻塞状态
阻塞状态->(调用join()的线程执行完毕/sleep()方法结束/阻塞条件解除)->就绪状态
运行状态->(线程执行完毕/stop()/interrupt())->终止状态
线程休眠sleep()
sleep(long millis)方法使得线程由运行到阻塞。线程休眠,交出CPU,但是不释放锁,使得当前线程暂缓执行,等到预期时间(睡眠时间截至)再恢复执行。
注意:
1.参数的毫秒。
2.调用sleep会抛出一个受查异常,需要trycatch接收,或者throws继续往回扔。
线程让步yield()
yield()方法使得线程由运行状态到就绪状态。暂停当前线程,同样不释放锁,交出CPU,但是无法控制CPU具体被交出的时间,回到就绪状态时拥有相同优先权的线程获得争夺CPU的机会。
** 等待其他线程终止再执行join()**
在一个线程A中通过另一个线程B.调用join方法。让线程A休眠,让出CPU,释放对象锁,等待B线程执行完毕再恢复A线程的执行。
在后台,join()实际上时完成了对wait()的封装。
线程终止的3种方式,由运行到终止
1.手动设置flag标志位
把代码放入到flag中循环中,从外部通过修改flag的值是之停止。这种方式又称为人工设置,手动停止。
2.stop()停止线程
可以利用Thread()提供的stop()方法停止线程。但是因为该方法不安全所以已经被@Depreciated标记,意思为不建议使用。
3.interrupt()方法设置中断状态
interrupt()方法只是将线程的状态修改为了中断状态。我们通过在线程中检测isInterrupted()判断是否是中断状态,这个方法只是将线程的状态修改为中断状态而已。他不会直接中断一个正在运行的线程。此方法只是给线程传递一个中断信号。我们的程序可以根据此信号来判断是否需要手动终止。
注意:
当我们的线程中使用了wait,sleep,join方法时,我们的线程就存在从运行状态到阻塞状态的转换的过程,但是如果和isInterrupted()就会抛出异常。本来我们调用interrupt()将线程状态修改成了中断,我们调用isInterrupted()返回应该时true,但是碰上了wait等。进入了catch,异常块。系统会将true又改回了false。这样就退出不了了。所以我们需要在异常块中手动return退出。
class MyRunnable implements Runnable{
@Override
public void run(){
for(int i=1;i>0;i++) {
try {
Thread.sleep(1000);
Boolean bool = Thread.currentThread().isInterrupted();
System.out.println("状态" + bool);
System.out.println(Thread.currentThread().getName() + "正常运行第" + i + "次");
} catch (InterruptedException e) {
System.out.print("退出了");
Boolean bool = Thread.currentThread().isInterrupted();
System.out.println(bool);return;
}
}
}
}
public class Test{
public static void main(String[] args) {
Runnable runnable = new MyRunnable();
System.out.println("开始了");
Thread thread = new Thread(runnable);t
hread.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
System.out.println("结束了");
}
}
守护线程
java中一共有两种线程用户线程和守护线程。守护线程是一种特殊的线程,又可以称为陪伴线程。
我们如何判断这个线程是不是守护线程,Thread类提供了isDaemon();返回值为true表示为守护线程,返回值为false表示为用户线程。守护线程的生命周期时从启动到最后一个用户线程结束时终止,也就是说守护线程随进程同时推销。
如何将一个用户线程修改为守护线程
Thread类提供一个方法public final void setDaemon(boolean on)
将我们启动的线程修改为守护线程。举例代码如下:
class MyRunnable implements Runnable{
@Overridepublic void run(){
if(Thread.currentThread().isDaemon()==false){
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}else{
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"守护进程");
}
}
}
}
public class Test{
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
Thread thread1 = new Thread(runnable);
thread.setDaemon(true);
System.out.println("开始");
thread1.start();
thread.start();
thread1.join();
System.out.println("结束");
}
}