JUC并发编程(面试)

1:同步与异步                                                 16:park()与unpark()
2:start()和run()                                               17:park(),unpark()&wait(),notify()
3:sleep() 与 yield()                                         18:死锁
4:线程优先级                                                 19:Lock接口
5:join()
6:join(毫秒数)
7:interrupt() 方法
8:提前结束线程
9:守护线程
10:临界区与竞态条件(如何解决)
11:synchronized
12:线程8锁
13:线程安全性分析
14:wait()和notify(),notifyAll()
15:sleep()与wait()方法对比


同步与异步:

  • 需要等待结果返回,才能继续运行就是同步
  • 不需要等待结果返回,就能继续运行就是异步


start()和run()

区别:

  • 调用start()开启一个新的线程,调用run()方法就是普通方法的调用,不会创建新线程。
  • 调用start()方法,会执行run()方法中的代码。
  • start()方法不能多次调用,多次调用会出现IllegalThreadsStateException异常。


sleep() 与 yield()

sleep():让线程进入睡眠

  • 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)。

  • 其它线程可以使用 interrupt() 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException。

  • 睡眠结束后的线程未必会立刻得到执行,会先进入就绪状态等待cpu分配时间片。

  • 建议用 TimeUnit(jdk1.5之后) 的 sleep 代替 Thread 的 sleep 来获得更好的可读性。

    //都是睡眠1秒
    TimeUnit.SECONDS.sleep(1);
    Thread.sleep(1000);
    

yield():让运行状态线程进入就绪

  • 调用 Thread.yield() 会让当前线程放弃当前时间片,从 Running(运行状态) 进入 Runnable 就绪状态,然后调度执行其它线程
  • 具体的实现依赖于操作系统的任务调度器

二者区别:

  • sleep()会释放当前线程占有的时间片,直到睡眠时间结束或被interrupt() 打断后,cpu才会重新为其分配时间片等待cpu重新调用。
  • yield():同样会让出时间片,等待cpu重新为其分配时间片,cpu重新调度,只不过没有睡眠时间。


线程优先级

线程优先级后会提示任务调度器去优先调度该线程,但仅仅只是提示,最终的任务调度情况还得由调度器决定,比如cpu比较繁忙时,优先级高的线程会获得更多的时间片。而cpu空闲时,优先级甚至会被忽略进而导致不起作用

设置优先级:

 t1.setPriority(n);
 //n[ 1 , 10 ]
 //1:最小优先级
 //5:默认优先级
 //10:最大优先级


join():让当前线程等待另一个线程执行结束后再继续执行当前线程

案例:

    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("开始");
            try {
   
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
            log.debug("结束");
            r = 10;
        });
        t1.start();
        t1.join();
        log.debug("结果为:{}", r);
        log.debug("结束");
    }
当前案例执行结果为 **r=0** 而不是 **r=10**

分析:

因为主线程和线程 t1 是并行执行的,t1 线程需要 1 秒之后才能算出 r=10
而主线程一开始就要打印 r 的结果,所以只能打印出 r=0。

解决方案:
想要让最终结果为r=10,就需要让主线程等待t1线程执行完毕后,主线程再去打印最终结果(异步变为同步)。即调用join() 方法。



join(毫秒数):当前线程等待另一个线程

解释: 当前线程等待另一个线程执行,与join() 这个无参数的方法不同,join()方法会让当前线程等待另一个线程结束。而join(500) 表示当前线程最多等待另一个线程500毫秒,如果在5秒没另一个线程没有执行完毕,将不再等待,继续执行当前线程。

static int r1 = 0;
    public static void main(String[] args) throws InterruptedException {
   
        test3();
    }

    public static void test3() throws InterruptedException {
   
        Thread t1 = new Thread(() -> {
   
            try {
   
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
            r1 = 10;
        });
        long start = System.currentTimeMillis();
        t1.start();
        // 线程执行结束会导致 join 结束
        t1.join(
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值