本文主要讲解:
- 八种创建线程的方式
- implements Runnable:见源码RunnableDemo.java
- extends Thread:见源码ThreadDemo.java
- 使用线程池:见源码ThreadPoolDemo.java
- 使用线程工厂:见源码ThreadFactoryDemo.java
- implements Callable:见源码CallableDemo.java
- implements FutureTask:见源码FutureTaskDemo.java
- 使用注解@Async:见源码AsyncDemo.java
- 定时器Timer创建线程:见源码TimerDemo.java
- 正确停止线程的方式
- Volatile停止线程失效的场景
本文源码地址:A01_实现线程的方式、A02_正确停止线程
欢迎star我的:Github
正文开始
八种创建线程的方式
其实这八种创建线程的方式本质上可以归结为一种方式:那就是new Thread();因为源码最终都是调用该方法创建线程的。
- implements Runnable:
public class RunnableDemo implements Runnable{
@Override
public void run() {
System.out.println("i am RunnableDemo");
}
@Test
public void test(){
RunnableDemo r = new RunnableDemo();
Thread t = new Thread(r);
t.start();
}
@Test
public void test2(){
new Thread(()->{
System.out.println("i am 匿名内部类");
}).start();
}
}
- extends Thread:
public class ThreadDemo extends Thread{
@Override
public void run() {
System.out.println("i am ThreadDemo");
}
@Test
public void test() {
ThreadDemo t = new ThreadDemo();
t.start();
}
}
- 使用线程池:
public class ThreadPoolDemo {
ExecutorService pools = Executors.newFixedThreadPool(10);
@Test
public void test() {
pools.submit(() -> {
System.out.println("ThreadPoolDemo");
});
}
}
- 使用线程工厂:
在这里插入代码片
- implements Callable:
public class CallableDemo implements Callable {
@Override
public Object call() throws Exception {
System.out.println("i am CallableDemo");
Thread.sleep(2000);
return "i am CallableDemo return";
}
@Test
public void test() throws InterruptedException {
ExecutorService exec = Executors.newFixedThreadPool(10);
// Future future = exec.submit(this::call);
Future future = exec.submit(new CallableDemo());
Thread.sleep(2000);
System.out.println("\n=======test=========");
try {
System.out.println(future.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
- implements FutureTask:
在这里插入代码片
- 使用注解@Async:
在这里插入代码片
- 定时器Timer创建线程:
在这里插入代码片
正确停止线程的方式
- 使用interrupt
public class StopThread {
@Test
public void test() throws Exception {
Thread t = new Thread(() -> {
int count = 0;
while (!Thread.currentThread().isInterrupted()) {
System.out.println("======" + (count++) + "=====");
}
});
t.start();
Thread.sleep(5);
t.interrupt();
}
//在sleep的情况下,能否感受到中断
@Test
public void test1() throws Exception {
Thread t = new Thread(() -> {
int count = 0;
while (!Thread.currentThread().isInterrupted()) {
System.out.println("======" + (count++) + "=====");
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
//如果后续方法需要捕捉到中断,需要在此处加上 interrupt
Thread.currentThread().interrupt();
}
}
});
t.start();
Thread.sleep(50);
t.interrupt();
}
}
- 使用volatile
public class VolatileStopThread extends Thread {
volatile boolean flag = false;
@Override
public void run() {
int num = 0;
while (!flag && num <= 1500) {
if (num / 15 == 0) {
System.out.println(++num);
}
}
}
@Test
public void test() throws Exception{
VolatileStopThread vs = new VolatileStopThread();
Thread t = new Thread(vs);
t.start();
Thread.sleep(5000);
vs.flag=true;
}
}
Volatile停止线程失效的场景
- 因为阻塞导致的失效
- 失效原因:失效原因是 BlockingQueue 的put 操作会引起 阻塞
public void testnoAction() throws InterruptedException {
ArrayBlockingQueue queue = new ArrayBlockingQueue(8);
Produce p = new Produce(queue);
Thread t = new Thread(p);
t.start();
Consumer c = new Consumer(queue);
while (c.needmoreNums()) {
System.out.println(c.queue.take() + "被消费了");
Thread.sleep(100);
}
System.out.println("消费者结束了");
p.flag = true;
System.out.println("p.flag:" + p.flag);
}
- 生产者
class Produce implements Runnable {
public volatile boolean flag = false;
BlockingQueue queue;
public Produce(BlockingQueue q) {
this.queue = q;
}
@Override
public void run() {
int num = 0;
try {
while (num <= 1000 && !flag) {
if (num % 50 == 0) {
//此处因为一直在put,而队列的容量只有8个,所以装不下的时候,发送了阻塞
queue.put(num);
System.out.println("queue.put(num):" + num);
}
num++;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("Produce end");
}
}
}
- 消费者
class Consumer {
BlockingQueue queue;
public Consumer(BlockingQueue q) {
this.queue = q;
}
public boolean needmoreNums() {
if (Math.random() > 0.97) {
return false;
}
return true;
}
}