start,join,run,countDownLatch区别

1.start:主线程启动时候会执行子线程继承的run方法;

主线程:

public static void main(String[] args) throws Exception{

        Son son=new Son();
        son.start();

}

子线程: 重写Thread方法

public class Son extends Thread{

    @Override
    public void run(){
        System.out.println("子线程执行开始。。。2"+Thread.currentThread().getName());

        try{
            Thread.sleep(3000);
        }catch(Exception e){
            e.printStackTrace();
        }
        System.out.println("子线程执行结束。。。4");

    }


}

运行主方法结果如下:

        子线程执行开始。。。2Thread-0

        子线程执行结束。。。4

主线程启动时候会执行子线程继承的run方法;

2.join:等待上一个线程执行完毕,再去执行下一个线程;

public static void main(String[] args) throws Exception{

        Son son=new Son();
        son.start();
        son.join();
        son.run();

}

运行主方法结果如下:

        子线程执行开始。。。2Thread-0

        子线程执行结束。。。4

        子线程执行开始。。。2main

        子线程执行结束。。。4

1).当join未输入参数时【初始值为0】:先会执行子线程,等子线程执行完毕;主线程再去调son类中的run方法。

 2).当join输入参数,小于子线程整体流程完成时间:会等待子线程启动完毕,等待1000后会启动主线程。

public static void main(String[] args) throws Exception{

        Son son=new Son();
        son.start();
        son.join(1000);
        son.run();

}

运行主方法结果如下:

        子线程执行开始。。。2Thread-0

        子线程执行开始。。。2main

        子线程执行结束。。。4

        子线程执行结束。。。4

join源代码如下:

3.countDownLatch :计数器,类似于栅栏,当计算器为0时,会使主线程运行。

        1)先创建worker类:

public class Worker extends Thread{

    private String name;
    
    private Long time;
    
    private CountDownLatch countDownLatch ;

    public Worker (String name,Long tine,CountDownLatch countDownLatch){
        this.name=name;
        this.time=time;
        this.countDownLatch=countDownLatch;
    }

    @Override
    public void run(){
        try{
            System.out.println(String.format("%s%s",name,"开始工作"));
            Thread.sleep(3000);
            System.out.println(String.format("%s%s%s",name,"工作完成,消耗时间=",time));
            countDownLatch.countDown();
            System.out.println(String.format("%s%s","count",countDownLatch.getCount()));          
        }catch(Exception e){
            e.printStackTrace();
        } 
    }

}

        2)运行main方法:

public static void main(String[] args){

       try{
            CountDownLatch countDownLatch=new CountDownLatch(2);
            Worker worker0=new Worker("worker0",new BigDecimal(Math.random()*2000+3000).setScale(2,BigDecimal.ROUND_HALF_UP).longValue(),countDownLatch);
            Worker worker1=new Worker("worker1",new BigDecimal(Math.random()*2000+3000).setScale(2,BigDecimal.ROUND_HALF_UP).longValue(),countDownLatch);
            Worker worker2=new Worker("worker2",new BigDecimal(Math.random()*2000+3000).setScale(2,BigDecimal.ROUND_HALF_UP).longValue(),countDownLatch);
            worker0.start();
            worker1.start();
            countDownLatch.await();
            System.out.println(String.format("%s%s","工作完成,消耗时间=",Thread.currentThread().getName()));
            worker2.start();
            
        }catch(Exception e){
            e.printStackTrace();
        } 

}

运行主方法结果如下:

        

         3)运行主方法结论:worker2线程会等待worker0,worker1线程执行完毕才会执行;

        4)countDownLatch 与join不同点时,可以灵活的设置countDownLatch.countDown()位置,worker2线程不需要等待worker0,worker1线程执行完毕才会执行,可以设置为worker0,worker1线程工作时就启动worker2线程。

public class Worker extends Thread{

    private String name;
    
    private Long time;
    
    private CountDownLatch countDownLatch ;

    public Worker (String name,Long tine,CountDownLatch countDownLatch){
        this.name=name;
        this.time=time;
        this.countDownLatch=countDownLatch;
    }

    @Override
    public void run(){
        try{
            System.out.println(String.format("%s%s",name,"开始工作"));
            //调整countDownLatch.countDown位置
            countDownLatch.countDown();
            Thread.sleep(3000);
            System.out.println(String.format("%s%s%s",name,"工作完成,消耗时间=",time));
            System.out.println(String.format("%s%s","count",countDownLatch.getCount()));          
        }catch(Exception e){
            e.printStackTrace();
        } 
    }

}

运行主方法结果如下:

 结论:与join最大的区别在于,当countDownLatch计数器为0时,其它线程就会相应执行,而不会等待Thread执行完毕;当join控制线程顺序时,必须等待Thread执行完毕才会继续执行下一个线程。

CountDownLatch 是一个 Java 并发包中的工具类,它可以让一个或多个线程等待其他线程执行完毕后再继续执行。具体来说,CountDownLatch 通过一个计数器来实现。在一个或多个线程中调用 CountDownLatch 的 await() 方法等待计数器归零,而在另外的线程中调用 CountDownLatchcountDown() 方法将计数器减一,当计数器变为 0 时,所有等待的线程都会被唤醒。 下面是一个简单的例子,假设我们有一个需求:在一个线程中生成 10 个随机数,而另一个线程需要等待这 10 个随机数生成完毕后才能继续执行。我们可以使用 CountDownLatch 来实现这个需求: ```java import java.util.Random; import java.util.concurrent.CountDownLatch; public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); RandomNumberGenerator generator = new RandomNumberGenerator(latch); ResultProcessor processor = new ResultProcessor(latch); generator.start(); processor.start(); generator.join(); processor.join(); } static class RandomNumberGenerator extends Thread { private final CountDownLatch latch; public RandomNumberGenerator(CountDownLatch latch) { this.latch = latch; } @Override public void run() { Random random = new Random(); for (int i = 0; i < 10; i++) { int randomNumber = random.nextInt(100); System.out.println("Generated random number: " + randomNumber); } latch.countDown(); } } static class ResultProcessor extends Thread { private final CountDownLatch latch; public ResultProcessor(CountDownLatch latch) { this.latch = latch; } @Override public void run() { System.out.println("Waiting for random numbers to be generated..."); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("All random numbers have been generated."); } } } ``` 在这个例子中,我们创建了一个 CountDownLatch 对象,并将其计数器初始化为 1。然后我们创建了两个线程:RandomNumberGenerator 线程用于生成随机数,ResultProcessor 线程用于等待随机数生成完毕。在 RandomNumberGenerator 线程中,我们使用 for 循环生成 10 个随机数,并在最后调用 countDown() 方法将计数器减一。在 ResultProcessor 线程中,我们使用 await() 方法等待计数器归零,然后输出一条消息表示随机数已经生成完毕。 需要注意的是,在主线程中我们必须使用 join() 方法等待 RandomNumberGenerator 线程和 ResultProcessor 线程执行完毕,否则程序会直接退出而不会等待它们执行完毕。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值