概述:本文主要讲述Java并发中的常见问题,内容涵盖多线程的实现、线程安全、线程安全集合类、线程阀、线程池等内容。
第一部分 分布式计算、并行计算、并发计算
1.1 并行计算与分布式计算
- 级别上。并行计算借助于并行算法与并行编程语言,实现进程级并行和线程级并行;分布式计算将任务分成小块分配到各个计算机上执行,属于计算机之间的并行。
- 粒度上。并行计算中,处理器之间交互频繁,粒度细;分布式计算中,处理器之间交互不频繁,粒度粗。
1.2 并发计算与分布式计算
并发使用多线程技术,使有限资源达到最大利用价值;分布式在资源紧缺时增加服务器资源。
第二部分 Java中的线程
2.1 线程实现的三种方法
2.1.1 继承Thread类
- 实现方法:继承Thread类,重写run()方法。
- 优缺点:一个Java类只能继承一个父类。
- 代码示例
/*
* 继承Thread类实现多线程
* **/
public class Test {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
}
}
class MyThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("继承Thread类实现多线程");
}
}
2.1.2 实现Runnable接口
- 实现方法:子类实现Runnable接口,并重写run()方法。将Runnable对象作为参数构造Thread类对象。
- 代码示例
/**
* 实现Runnable接口*/
public class Test {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread t = new Thread(runnable);
t.start();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("实现Runnable接口");
}
}
2.1.3 实现Callable接口
实现方法:
- 实现Callable接口,覆盖call()方法,其中call()方法有返回值;
- 利用Callable对象实例化FutureTask对象;
- 利用FutureTask对象构造Thread对象。
FutureTask类有get()方法获取call()方法返回值,get()方法会阻塞线程,直到获取返回值。
代码示例
/**
* 实现Callable接口*/
public class Test {
public static void main(String[] args) {
MyCallable callable = new MyCallable();
FutureTask<String> fetureTask = new FutureTask<>(callable);
Thread t = new Thread(fetureTask);
t.start();
System.out.println("主线程start");
try {
System.out.println(fetureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("主线程end");
}
}
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(3000);
System.out.println("实现Callable接口");
return "call()方法执行完毕";
}
}
输出:
主线程start
实现Callable接口
call()方法执行完毕
主线程end
2.2 线程中断机制
2.2.1 调用Thread.stop()方法
该方法强制停止一个线程,并抛出ThreadDeath对象作为异常。该异常不应该被捕获,这样才能使线程真正终止。Stop()方法不安全,不建议使用。
2.2.2 调用Thread.interrupt()方法
Java中断机制是一种协作机制,通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理中断。每个线程都有一个boolean类型标识,代表着是否有中断请求。当线程t1向中断线程t2时,只需将t2的中断标识设置为true,然后t2可以选择在合适的时候检测中断标志位并处理该中断请求,甚至可以不理会该请求。
Thread类提供了三个中断方法:
(1)boolean interrupted():测试当前线程是否已经中断。线程的中断状态由该方法清除,即调用一次该方法后将清除线程的中断转态。
(2)boolean isInterrupted():测试线程是否已经中断,线程的中断状态不受该方法的影响。
(3)void interrupt():中断线程,将线程额中断状态设置为true
代码示例
public class Test {
public static void main(String[] args) {
System.out.println("主线程开始");
MyThread t = new MyThread();
t.start();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();// 中断线程
}
}
class MyThread extends Thread {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted())// 处理中断请求
break;
else {
try {
Thread.currentThread().sleep(100);
} catch (InterruptedExcept