转载

多线程

线程同步

线程状态

多线程

  1. 新建(new):新创建线程

    • 继承Thread
    • 实现Runnable 或者Callable接口
  2. 可运行(Runnable):线程对象创建后,其他线程(如main线程)调用该线程对象start方法,使其位于可运行线程池中,等待cpu调度
  3. 运行中(running):可运行状态线程获取cpu时间片,执行程序代码
  4. 阻塞(block):线程因某种原因出让了cpu时间片,暂时停止运行,阻塞的情况分三种:

    • 等待阻塞:运行线程执行o.wait()方法,jvm将其放入等待队列中,直到其被其他线程唤醒(调用o.notify()或者o.notifyAll()方法), 此状态下线程会释放锁
    • 同步阻塞:运行线程竞争获取对象锁时,若该对象锁被别的线程占用, 则jvm会把该线程放入锁池(lock pool)中
    • 运行线程执行Thread.sleep或 t.join()方法,或者发出了I/O 请求时,jvm会把该线程置为阻塞。当 sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行状态
  5. 销亡(dead):线程 run()、 main()方法执行结束,或者因异常退出了run()方法,则该线程结 束生命周期。死亡的线程不可再次复生

线程安全

当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程讲如何交替执行,并且在主线程中不需要做额外的同步或协调,这个类都能表现出正确的行为,那么就程这个类是线程安全的。

线程安全实现策略

1. 线程封闭:线程封闭的对象只能有一个线程拥有,对象被封闭在线程中,并且只能由这个 线程修改 
2.只读共享:在没有额外的同步的情况下,共享的只读对象可以由多个线程并发访问,但任何线程都不能修改他。共享的只读对象包括不可变对象和事实不可变对象。 
3.线程安全共享:线程安全的对象在其内部实现同步,因此多个线程可以通过对象的共有接口 进行访问而不需要进一步的同步 
4.保护对象:被保护的对象只能通过持有特定的锁来访问。保护对象包括封装在其他的线程安全的对象中的对象,以及已发布的并且由某个特定锁保护的对象。

无状态对象一定是线程安全的

不可变对象一定是线程安全的

静态工具类的线程安全??

工具类能否设计成单例?如果能最好。单例能减少创建类和分配内存的开销,减少垃圾回收次数。

工具类能否设计成不变类?如果能最好,不变类天生线程安全!

线程中断

  1. interrupt()只是改变中断状态而已. interrupt()不会中断一个正在运行的线程。这一方法实际上完成的是,给受

阻塞的线程抛出一个中断信号,这样受阻线程就得以退出阻塞的状态。更确切 的说,如果线程被Object.wait,

Thread.join和Thread.sleep三种方法之一阻塞,    那么,它将接收到一个中断异常(InterruptedException),

从而提早地终结被阻塞状态。如果线程没有被阻塞,这时调用interrupt()将不起作用;否则,线程就将得到InterruptedException

异常(该线程必须事先预备好处理此状况),接着逃离阻塞状态

2.interrupted()方法会检查当前线程的中断状态,如果为 "被中断状态 "则改变当前线程为 "非中断状态 "并返回

true,如果为 "非中断状态 "则返回false,它不仅检查当前线程是否为中断状态,而且在保证当前线程状态恢复为非中

断状态,所以它叫 "interrupted ",是说中断的状态已经结束(到非中断状态了)

3.isInterrupted()方法则仅仅检查线程对象对应的线程是否是中断状态,并不改变它的状态.

interrupt 中断操作时,非自身打断需要先检测是否有中断权限,这由jvm的安全机制配置;

如果线程处于sleep, wait, join 等状态,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常;

如果线程处于I/O阻塞状态,将会抛出ClosedByInterruptException(IOException的子类)异常;

如果线程在Selector上被阻塞,select方法将立即返回;

如果非以上情况,将直接标记 interrupt 状态;

注意:interrupt 操作不会打断所有阻塞,只有上述阻塞情况才在jvm的打断范围内,如处于锁阻塞的线程,不会受 interrupt 中断;

原文  https://segmentfault.com/a/1190000021290985
正文到此结束
Loading...