- 创建线程两种方法:扩展Thread 类 ;实现Runnable 接口 。
- Thread.States的线程状态:NEW、RUNNABLE、BLOCKED、WAITING、TIME_WAITING、TERMINATED
- 操作系统线程状态:创建状态 、就绪状态 、运行状态 、阻塞状态 、死亡状态
callable区别:
- 接口。有简单类型参数,与call()方法的返回类型相对应。
- 声明了call()方法。执行器运行任务时,该方法会被执行器执行。它必须返回声明中指定类型的对象。
- call()方法可以抛出任何一种校验异常。可以实现自己的执行器并重载afterExecute()方法来处
理这些异常 。
callable代码示例: ```java // 有泛型、有返回值 class MyCallable implements Callable
{ @Override public String call() throws Exception { Thread.sleep(5000);return "hello world call() invoked!";
} }
public class Main {
public static void main(String[] args) throws ExecutionException,InterruptedException {
MyCallable myCallable = new MyCallable();
// 设置Callable对象,泛型表示Callable的返回类型
FutureTask
- 锁对象的作用> 1. 这个对象内部得有一个标志位(state变量),记录自己有没有被某个线程占用。最简单的情况是这个state有0、1两个取值,0表示没有线程占用这个锁,1表示有某个线程占用了这个锁。> 2. 如果这个对象被某个线程占用,记录这个线程的thread ID。> 3. 这个对象维护一个thread id list,记录其他所有阻塞的、等待获取拿这个锁的线程。在当前线程释放锁之后从这个thread id list里面取一个线程唤醒。- 锁如何实现> 在对象头里,有一块数据叫Mark Word。在64位机器上,Mark Word是8字节(64位)的,这64位中有2个重要字段:锁标志位和占用该锁的thread ID。因为不同版本的JVM实现,对象头的数据结构会有各种差异。- 实现生产者消费者思路> 1. 内存队列本身要加锁,才能实现线程安全。(必须实现)> 2. 阻塞。当内存队列满了,生产者放不进去时,会被阻塞;当内存队列是空的时候,消费者无事可做,会被阻塞。> 3. 双向通知。消费者被阻塞之后,生产者放入新数据,要notify()消费者;反之,生产者被阻塞之后,消费者消费了数据,要notify()生产者。>> - 如何阻塞> - 线程自己阻塞自己,也就是生产者、消费者线程各自调用wait()和notify()。> - 用一个阻塞队列,当取不到或者放不进去数据的时候,入队/出队函数本身就是阻塞的。> - 如何双向通知?> - wait()与notify()机制。> - Condition机制。// 单个生产者和消费者的情况```java// 我的理解: 重点是先把阻塞队列实现了,剩下的都好说.jpg// 阻塞队列public class MyQueue {private String[] data = new String[10];private int getIndex = 0;private int putIndex = 0;private int size = 0;public synchronized void put(String element) {if (size == data.length) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}data[putIndex] = element;++putIndex;if (putIndex == data.length) putIndex = 0;++size;notify();}public synchronized String get() {if (size == 0) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}String result = data[getIndex];++getIndex;if (getIndex == data.length) getIndex = 0;--size;notify();return result;}}public class Main {public static void main(String[] args) {MyQueue myQueue = new MyQueue();ProducerThread producerThread = new ProducerThread(myQueue);ConsumerThread consumerThread = new ConsumerThread(myQueue);producerThread.start();consumerThread.start();}}// 生产者public class ProducerThread extends Thread {private final MyQueue myQueue;private final Random random = new Random();private int index = 0;public ProducerThread(MyQueue myQueue) {this.myQueue = myQueue;}@Overridepublic void run() {while (true) {String tmp = "ele-" + index;myQueue.put(tmp);System.out.println("添加元素:" + tmp);index++;try {Thread.sleep(random.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}}}}// 消费者public class ConsumerThread extends Thread {private final MyQueue myQueue;private final Random random = new Random();public ConsumerThread(MyQueue myQueue) {this.myQueue = myQueue;}@Overridepublic void run() {while (true) {String s = myQueue.get();System.out.println("\t\t消费元素:" + s);try {Thread.sleep(random.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}}}}
// 多个消费者和生产者 Ps感觉不太对。。。。
// notify 唤醒的可能还是生产者,感觉用到Condition
// 把if改成whire
public class MyQueue2 {private String[] data = new String[10];private int getIndex = 0;private int putIndex = 0;private int size = 0;public synchronized void put(String element) {//if (size == data.length) {while (size == data.length) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}put(element);} else {put0(element);notify();}}private void put0(String element) {data[putIndex] = element;++putIndex;if (putIndex == data.length) putIndex = 0;++size;}public synchronized String get() {// if (size == 0) {while (size == 0) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}return get();} else {String result = get0();notify();return result;}}private String get0() {String result = data[getIndex];++getIndex;if (getIndex == data.length) getIndex = 0;--size;return result;}}
伪代码:生产消费线程 ```java public void enqueue() {
synchronized (queue) {while (queue.full()) {queue.wait();} //... 数据入列queue.notify(); // 通知消费者,队列中有数据了。}
}
public void dequeue() {
synchronized (queue) {while (queue.empty()) {queue.wait();} // 数据出队列queue.notify(); // 通知生产者,队列中有空间了,可以继续放数据了。}
}
```
- InterruptedException
如果不是那些显示捕获这个异常的方法,那么不会抛出异常
thread.interrupted()的精确含义是“唤醒轻量级阻塞”,而不是字面意思“中断一个线程”。
- 轻量级阻塞和重量级阻塞

关于interrupt
thread.isInterrupted()与Thread.interrupted()的区别因为 thread.interrupted()相当于给线程发送了一个唤醒的信号,所以如果线程此时恰好处于WAITING或者TIMED_WAITING状态,就会抛出一个InterruptedException,并且线程被唤醒。而如果线程此时并没有被阻塞,则线程什么都不会做。但在后续,线程可以判断自己是否收到过其他线程发来的中断信号,然后做一些对应的处理。
这两个方法都是线程用来判断自己是否收到过中断信号的,前者是实例方法,后者是静态方法。二
者的区别在于,前者只是读取中断状态,不修改状态;后者不仅读取中断状态,还会重置中断标志位。thread.isInterrupted()与Thread.interrupted()的区别
