多线程
-
1、线程:
-
(1) 线程是程序的最小执行单元
-
(2) 线程之间的关系:交互、互斥、同步
-
(3) 线程创建:构造方法
-
Thread()
-
Thread(String)
-
Thread(Runnable target)
-
Thread(Runnable target,String name)
//创建方式一:
Class ThreadName extends Thread{
}
//创建方式二:
class ThreadTest2 implements Runnable{
}
//创建方式三:
Thread thread = new Thread();
//创建方式四:
Thread thread = new Thread(String name);
//创建方式五:
Runnable rb = new Runnable();
Thread thread = new Thread(rd);
//创建方式六:
Runnable rb = new Runnable();
Thread thread = new Thread(rd,String name);
-
(4) 方法
void start(); //启动线程
static void sleep(long millis); //线程休眠、毫秒
static void sleep(long millis,int nanos);//休眠
void join(); //使其他线程等待当前线程终止
void join(long millis); //同上
void join(long millis,int nanos); //同上
static void yield(); //当前运行线程释放处理器资源
static Thread currentThread(); //获取当前线程引用,返回当前运行的线程引用
-
2、关于线程
-
start()方法来启动线程,真正实现了多线程运行,调用了run()方法;run()方法当作普通方法的方式调用。
-
CyclicBarrier让一组线程等待其他线程;CountDownLatch让一组线程等待某个事件发生。
-
Callable能够抛出checked exception。
-
start()方法让thread进去可运行状态(runnable),等待获取CPU的使用权。
-
3、线程间的状态转换:
-
-
- 新建(new):新创建了一个线程对象。
-
-
-
- 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
-
-
-
- 运行(running):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
-
-
-
- 阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
-
-
-
- (一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
-
-
-
- (二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
-
-
-
- (三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
-
-
-
- 死亡(dead):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
-
-
Java中sleep方法的几个注意点:
-
- Thread.sleep()方法用来暂停线程的执行,将CPU放给线程调度器。
-
- Thread.sleep()方法是一个静态方法,它暂停的是当前执行的线程。
-
- Java有两种sleep方法,一个只有一个毫秒参数,另一个有毫秒和纳秒两个参数。
-
- 与wait方法不同,sleep方法不会释放锁
-
- 如果其他的线程中断了一个休眠的线程,sleep方法会抛出Interrupted Exception。
-
- 休眠的线程在唤醒之后不保证能获取到CPU,它会先进入就绪态,与其他线程竞争CPU。
-
- 有一个易错的地方,当调用t.sleep()的时候,会暂停线程t。这是不对的,因为Thread.sleep是一个静态方法,它会使当前线程而不是线程t进入休眠状态。
-
4、JDK提供的用于并发编程的同步器:
-
- 同步器是一些使线程能够等待另一个线程的对象,允许它们协调动作。
-
- 最常用的同步器是CountDownLatch和Semaphore,不常用的是Barrier和Exchanger
-
5、SimpleDateFormat对象是线程不安全的;
-
6、TreadLocal
-
- 1、ThreadLocal的类声明:
-
public class ThreadLocal
可以看出ThreadLocal并没有继承自Thread,也没有实现Runnable接口。所以AB都不对。 -
- 2、ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。
所以ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立,C选项错。
由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问,
变量被彻底封闭在每个访问的线程中。所以E对。
- 2、ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。
-
- 3、ThreadLocal中定义了一个哈希表用于为每个线程都提供一个变量的副本:
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
/**
* The table, resized as necessary.
* table.length MUST always be a power of two.
*/
private Entry[] table;
}