多线程

一、守护线程

  1. 守护线程设置必须在start之前;如果在start之后,设定为守护线程,设定无效,且如果线程在执行过程中,将会抛出异常:IllegalThreadStateException
  2. 守护线程中创建的线程默认是守护线程,可以更改
  3. Timer是单线程且可以设置为守护线程;GC线程是典型的守护线程

二、Runnable和Callable区别

  1. Runnable需要实现run方法,Callable需要实现call方法
  2. run方法没有返回值,call方法需要有返回值
  3. run方法中的异常只能自己处理,不能抛出;call方法异常可以抛出
  4. 使用Thread创建线程时,Runnable可以直接作为入参或者使用FutureTask封装;Callable只能使用FutureTask封装,不能直接作为入参
  5. 使用ExecutorService创建线程时,Runnable可以直接使用execute或submit执行;Callable只能直接被submit执行,不能被execute执行;两者被FutureTask封装后,两者皆可

三、ThreadGroup---具体应用场景未找到

  创建线程时可以指定所属线程组,未指定则为当前线程所在线程组。通过线程组可以查看当前线程组内线程的数量和运行状况。

四、线程同步

  1. sleep和wait区别
    • sleep属于Thread静态方法;wait属于Object方法
    • sleep不释放锁;wait释放所
    • sleep属于静态方法,只能让当前线程进入block状态,所以Thread t=new Thread();t.start();t.sleep(1000);只会让当前线程进入等待状态,对t线程无效
    • wait方法必须在synchronized中,否则编译通过,运行时抛出异常
  2. yield和join方法
    • yield方法让当前线程工running状态进入runnable状态,使得其他线程有重新竞争的机会
    • join方法实质调用的实wait方法,当相关线程执行结束后自动唤醒。等待调用线程结束后,将继续执行当前线程;调用时,线程处于不活动状态,则不进行阻塞
  3. 实现线程同步的方法
    • 使用synchronized和Lock使得同一时间只有一个线程执行代码块
    • 使用volatile保证变量的可见性??
    • 使用wait/nofity/notifyAll或者await/signal/signalAll实现多个线程间同步
    • 使用CountDownLatch,CyclicBarrier和Semaphore实现多线程同步??

五、线程安全

  1. 三大概念:可见性,原子性,有序性
  2. synchronized和Lock(ReentrantLock    ReentrantReadWriteLock)区别
    • Lock可以实现synchronized效果,lock.lock()--进入锁;lock.unlock()--释放锁
    • Condition c=lock.newCondition()   c.await()和wait同效果--释放当前保持的锁,c.signal()和notify()同效果,signalAll和notifyAll相同----必须是同一个Condition
    • lock.tryLock()尝试获取锁,获取则返回true,未获取返回false;
    • lock.writeLock.lock()和lock.readLock.lock();读读锁不互斥,两个线程可以同时获取读锁;写写锁和读写锁互斥,必须等锁释放才能获取
  3. 线程安全方法
    • 使用ThreadLocal。使不同线程访问不同资源。
    • volatile保证变量的可见性,以及一定程度的有序性
    • 使用Atomic类进行原子性操作
    • 使用synchronized和Lock保证原子性和互斥性

六、线程间通信

  1. volatile,while轮询,synchronized和Lock共享内存
  2. 使用BlockingQueue阻塞队列
  3. wait/notify/notifyAll  join await/signal/signalAll线程间通知
  4. CountDownLatch,CyclicBerrier和Semaphore
  5. Callable接口返回数据
  6. 管道通信  java.io.PipedInputStream PipedOutStream

七、线程池

八、CountDownLatch,CyclicBarrier和Semaphore

  1. CountDownLatch实现类似计数器功能。构造函数CountDownLatch(int i);常用方法:await()方法--挂起当前线程;countDown()方法--计数器减一,直到减为0,所有挂起线程开始执行
  2. CyclicBarrier实现线程等待。构造函数CyclicBarrier(int parties);常用方法:await()--挂起线程,直到parties个数线程同时挂起,才开始执行。                                                                                             构造函数CyclicBarrier(int parties,Runnable barrierAction);挂起线程数为parties时,使用一个线程执行barrierAction,执行结束之后,所有挂起线程开始执行;如果barrierAction线程发生阻塞,则所有线程一直处于挂起状态
  3. Semaphore控制线程并发数。构造函数Semaphore(int permits);常用方法:acquire(),acquire(int permits)--获取单个或设定数量的许可,未获取,则一直等到;                                                                                                                                                                                         release(),release(int permits);释放许可                                                                                                                                                                                                                                                               tryAcquire(),tryAcquire(int permits)--尝试获取许可,如果获取返回true,否则返回false
  4. CountDownLatch和CyclicBarrier区别
    • CountDownLatch可以代码控制重新开启线程的时间;CyclicBarrier只能自动执行
    • ConntDownLatch不可以重用,countDown之后await失效;CyclicBarrier执行结束后可以重新使用
    • CountDownLatch理论是可以控制任何数量线程挂起,一般只控制一个,一般一个线程等待,等待其他线程执行结束;CyclicBarrier控制多个线程在某个状态等待,直到所有都到达这个状态,开始执行
  5. Semaphore类似于锁,可以控制并发线程的数量

九、其他

  1. new Thread(new Runnable(){public void run(){System.out.println("1111");}}){public void run(){System.out.println("2222");}}   既重写了Thread的run方法,又传入了Runnable实现,最后会执行哪个run方法?
    • 涉及匿名内部类调用父类构造函数;
    • 重写Thread的run方法可定执行,Runnable方法是否执行,根据run方法是否调用super.run();如果调用了,则执行。
      • super.run();System.out.println("2222"); 控制台结果:1111   2222
      • System.out.pringln(“2222”);super.run();控制台结果:2222  1111
      • System.out.pringln(“2222”);                   控制台结果:2222

     2、查看当前线程是否持有某对象的锁。Thread.holdsLock(obj);和sleep类似,只能查看当前线程是否持有某对象的锁,即使是使用其他线程对象执行此方法

     3、wait/notify/notifyAll+synchronized+信号量+while      信号量保证notify提前执行也可以正确执行;while保证假唤醒时可以继续判断      不要在字符串常量和全局变量使用wait

    

 

    

posted @ 2018-03-02 19:24  国际庄_码农  阅读(108)  评论(0)    收藏  举报