多线程常见方法及使用

常用方法

在这里插入图片描述在这里插入图片描述

sleep 与 yield

sleep

  1. 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)
  2. 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException异常
@Slf4j(topic = "c.TestInterrupt")
public class TestInterrupt {
    public static void main(String[] args) throws InterruptedException {
      Thread t1 = new Thread("t1"){
  	    public void run(){
  	  	  log.debug("enter sleep...");
  	  	  try{
			  Thread.sleep(2000);	
		  }catch(InterruptedException e){
		      log.debug("wake up...");
			  e.printStakeTrace();
			}
	  	  }
	  	 };        
	     t1.start();
	     
	     Thread.sleep(1000);
	     log.debug("interrupt...");
	     t1.interrupt();    
     }
 }       
  1. 睡眠结束后的线程未必会立刻得到执行,此刻CPU可能正在执行其他代码。
  2. 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性

yield

  1. 调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态,然后调度执行其它线程
  2. 具体的实现依赖于操作系统的任务调度器

join 方法详解

Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。

在A线程中调用了B线程的join()方法时,表示只有当B线程执行完毕时,A线程才能继续执行。

@Slf4j(topic = "c.Test10")
public class Test10 {
    static int r = 0;
    public static void main(String[] args) throws InterruptedException {
        test1();
    }
    private static void test1() throws InterruptedException {
        log.debug("开始");
        Thread t1 = new Thread(() -> {
            log.debug("开始");
            sleep(1);
            log.debug("结束");
            r = 10;
        },"t1");
        t1.start();
        t1.join();//t1执行结束后,主线程才会继续执行
        log.debug("结果为:{}", r);
        log.debug("结束");
    }
}

在这里插入图片描述

join的同步应用

  • 需要等待结果返回,才能继续运行就是同步
  • 不需要等待结果返回,就能继续运行就是异步
    在这里插入图片描述

有时效的join

static int r1 = 0;
static int r2 = 0;
public static void main(String[] args) throws InterruptedException {
	test3();
}
public static void test3() throws InterruptedException {
	Thread t1 = new Thread(() -> {
	sleep(2);
	r1 = 10;
	});
	long start = System.currentTimeMillis();
	t1.start();

	// 线程执行结束会导致join结束
	t1.join(1500);
	long end = System.currentTimeMillis();
	log.debug("r1: {} r2: {} cost: {}", r1, r2, end - start);
}

在这里插入图片描述

interrupt方法详解

1. 打断 sleep,wait,join 的线程

@Slf4j(topic = "c.Test11")
public class Test11 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.debug("sleep...");
            try {
                Thread.sleep(5000); // wait, join
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1");

        t1.start();
        Thread.sleep(1000);
        log.debug("interrupt");
        t1.interrupt();
        log.debug("打断标记:{}", t1.isInterrupted());//打断sleep、wait、join线程, 会清空打断状态
    }
}

在这里插入图片描述
2. 打断正常线程
正常运行的线程在被打断后,isInterrupted()的布尔值为true

@Slf4j(topic = "c.Test12")
public class Test12 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while(true) {
                boolean interrupted = Thread.currentThread().isInterrupted();
                if(interrupted) {
                    log.debug("被打断了, 退出循环");
                    break;
                }
            }
        }, "t1");
        t1.start();

        Thread.sleep(1000);
        log.debug("interrupt");
        t1.interrupt();
    }
}

主线程与守护线程

默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。

垃圾回收器线程就是一种守护线程

@Slf4j(topic = "c.Test15")
public class Test15 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    break;
                }
            }
            log.debug("结束");
        }, "t1");
        t1.setDaemon(true);//设置t1为守护线程
        t1.start();
        Thread.sleep(1000);
        log.debug("结束");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值