并发(2)
目录
6.通常线程有哪几种使用方式?
有三种使用线程的方法:
实现Runnable接口;
实现Callable接口;
集成Thread类。
实现Runnable和Callable接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过Thread来调用。可以说任务是通过线程驱动从而执行的。
7.基础线程机制有哪些?
Executor管理多个异步任务的执行,而无需程序员显式地管理线程的生命周期。这里的异步是指多个任务的执行互不干扰,不需要进行同步操作。
主要有三种Excutor:
1.CachedThreadPool:一个任务创建一个线程;
2.FixedThreadPool:所有任务只能使用固定大小的线程。
3.SingleThreadExecutor:相当于大小为1的FixedThreadPool。
Daemon
守护线程是程序运行时在后台提供服务的线程,不属于程序中不可或缺的部分。
当所有非守护线程结束时,程序也就终止,同时会杀死所有守护线程。
main()属于非守护线程。使用setDaemon()方法将一个线程设置为守护线程。
sleep()
Thread.sleep(millisec)方法会休眠当前正在执行的线程,Millisec单位为毫秒。
sleep()可能会抛出InterruptedException,因为异常不能跨线程传播回main()中,因此必须在本地进行处理。线程中抛出的其他异常也同样需要在本地进行处理。
yield()
对静态方法Thread.yield()调用声明了当前线程已经完成了声明周期中最重要的部分,可以切换给其他线程来执行。该方法只是对县城调度器的一个建议,而且也只是建议具有相同优先级的其他线程可以运行。
8.线程的中断方式有哪些?
一个线程执行完毕之后会自动结束,如果在运行过程中发生异常也会提前结束。
InterruptedException
通过调用一个线程的interrupt()来中断该线程,如果该线程处于阻塞,限期等待或者无限期等待状态,那么就会抛出InterruptedException,从而提前结束该线程。但是不能中断I/O阻塞和synchronized锁阻塞。
对于以下代码,在main()中启动一个线程之后再中断他,由于线程中调用了Thread.sleep()方法,因此会抛出InterruptedException,从而提前结束线程,不执行之后的语句。
interrupted()
如果一个线程的run()方法执行一盒无限循环,并且没有执行sleep()等会抛出InterruptedException的操作,那么调用线程的interrupt()方法就无法使线程提前结束。
但是调用interrupt()方法会设置线程的中断标记,此时调用Interrupt()方法会返回true。因此可以在循环体中使用interrupted()方法来判断线程是否处于中断状态,从而提前结束线程。
Excutor的中断操作
调用Excutor的shutdown()方法会等待线程都执行完毕后再关闭,但是如果调用的是shutdownNow()方法,则相当于调用每个线程的interrupt()方法。
9.线程的互斥同步方式有哪些?如何比较和选择?
Java提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是JVM实现的synchronized,而另一个是JDK实现的ReentrantLock。
1.锁的实现
synchronized时JVM实现的,而ReentrantLock是JDK实现的。
2.性能
新版本Java对Synchronized进行了很多优化,例如自旋锁等,synchronized与ReentrantLock大致相同。
3.等待可中断
当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。ReentrantLock可中断,而synchronized不行。
4.公平锁
公平锁是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来一次获得锁。synchronized中的锁是非公平的,ReentrantLock默认情况下也是非公平的,但是也可以是公平的。
5.锁绑定多个条件
一个ReentrantLock可以同时绑定多个Condition对象。
10.Synchronized可以作用在哪里?
对象锁
方法锁
类锁