文章目录
1、通过Thread的join方法
join主要是让父线程等待子线程结束之后父线程才能继续运行
public static void main(String[] args) throws InterruptedException {
System.out.println("---开启线程1---");
MyThread t1 = new MyThread("线程1");
t1.start();
t1.join();
System.out.println("---开启线程2---");
MyThread t2 = new MyThread("线程2");
t2.start();
t2.join();
System.out.println("---开启线程3---");
MyThread t3 = new MyThread("线程3");
t3.start();
t3.join();
}
static class MyThread extends Thread {
public MyThread(String name){
super(name);
}
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName()+"执行了");
}
}
打印结果
---开启线程1---
线程1执行了
---开启线程2---
线程2执行了
---开启线程3---
线程3执行了
2、FutureTask
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("---开启线程1---");
FutureTask<String> f1 = new FutureTask<>(new MyCall());
Thread t1 = new Thread(f1,"线程1");
t1.start();
System.out.println("线程1返回结果: " + f1.get());
System.out.println("---开启线程2---");
FutureTask<String> f2 = new FutureTask<>(new MyCall());
Thread t2 = new Thread(f2,"线程2");
t2.start();
System.out.println("线程2返回结果: " + f2.get());
System.out.println("---开启线程3---");
FutureTask<String> f3 = new FutureTask<>(new MyCall());
Thread t3 = new Thread(f3,"线程3");
t3.start();
System.out.println("线程3返回结果: " + f3.get());
}
static class MyCall implements Callable<String> {
@Override
public String call() throws Exception {
return Thread.currentThread().getName();
}
}
打印结果
---开启线程1---
线程1返回结果: 线程1
---开启线程2---
线程2返回结果: 线程2
---开启线程3---
线程3返回结果: 线程3
3、CountDownLatch(倒计数)
现在有如下3个线程
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("---开启线程1---");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
System.out.println("线程1执行了。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程1");
t1.start();
System.out.println("---开启线程2---");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(200);
System.out.println("线程2执行了。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程2");
t2.start();
System.out.println("---开启线程3---");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
System.out.println("线程3执行了。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程3");
t3.start();
}
它们的执行结果是
---开启线程1---
---开启线程2---
---开启线程3---
线程3执行了。。。
线程2执行了。。。
线程1执行了。。。
上面的输出是按照3、2、1输出的。如果现在要按照1、2、3的顺序进行输出,每个线程的sleep时间不能修改,该如何去处理?可以借助CountDownLatch
private static CountDownLatch c1 = new CountDownLatch(1);
private static CountDownLatch c2 = new CountDownLatch(1);
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("---开启线程1---");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
System.out.println("线程1执行了。。。");
c1.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程1");
t1.start();
System.out.println("---开启线程2---");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
c1.await();
Thread.sleep(200);
System.out.println("线程2执行了。。。");
c2.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程2");
t2.start();
System.out.println("---开启线程3---");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
c2.await();
Thread.sleep(100);
System.out.println("线程3执行了。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程3");
t3.start();
}
它们的执行结果是
---开启线程1---
---开启线程2---
---开启线程3---
线程1执行了。。。
线程2执行了。。。
线程3执行了。。。
4、wait、notify
private final static Object lock1 = new Object();
private final static Object lock2 = new Object();
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("---开启线程1---");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock1) {
try {
lock1.wait();
Thread.sleep(500);
System.out.println("线程1执行了。。。");
lock1.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "线程1");
t1.start();
Thread.sleep(10);//这个主要保证线程开启的顺序
System.out.println("---开启线程2---");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock1) {
try {
lock1.notify();
lock1.wait();
Thread.sleep(200);
System.out.println("线程2执行了。。。");
synchronized (lock2) {
lock2.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "线程2");
t2.start();
Thread.sleep(10);
System.out.println("---开启线程3---");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock2) {
try {
lock2.wait();
Thread.sleep(100);
System.out.println("线程3执行了。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "线程3");
t3.start();
}
打印结果
---开启线程1---
---开启线程2---
---开启线程3---
线程1执行了。。。
线程2执行了。。。
线程3执行了。。。
5、Condition(条件变量)
private static Lock lock = new ReentrantLock();
private static Condition condition1 = lock.newCondition();
private static Condition condition2 = lock.newCondition();
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("---开启线程1---");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
condition1.await();
Thread.sleep(500);
System.out.println("线程1执行了。。。");
condition1.signal();
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程1");
t1.start();
System.out.println("---开启线程2---");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
condition1.signal();
condition1.await();
Thread.sleep(200);
System.out.println("线程2执行了。。。");
condition2.signal();
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程2");
t2.start();
System.out.println("---开启线程3---");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
condition2.await();
Thread.sleep(100);
System.out.println("线程3执行了。。。");
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程3");
t3.start();
}
打印结果
---开启线程1---
---开启线程2---
---开启线程3---
线程1执行了。。。
线程2执行了。。。
线程3执行了。。。
6、CyclicBarrier(回环栅栏)
private static CyclicBarrier barrier1 = new CyclicBarrier(2);
private static CyclicBarrier barrier2 = new CyclicBarrier(2);
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("---开启线程1---");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
System.out.println("线程1执行了。。。");
barrier1.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}, "线程1");
t1.start();
System.out.println("---开启线程2---");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
barrier1.await();
Thread.sleep(200);
System.out.println("线程2执行了。。。");
barrier2.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}, "线程2");
t2.start();
System.out.println("---开启线程3---");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
barrier2.await();
Thread.sleep(100);
System.out.println("线程3执行了。。。");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}, "线程3");
t3.start();
}
打印结果
---开启线程1---
---开启线程2---
---开启线程3---
线程1执行了。。。
线程2执行了。。。
线程3执行了。。。
5、线程池
5.1、单线程化线程池
private static ExecutorService executorService = Executors.newSingleThreadExecutor();
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("---开启线程1---");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
System.out.println("线程1执行了。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程1");
System.out.println("---开启线程2---");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(200);
System.out.println("线程2执行了。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程2");
System.out.println("---开启线程3---");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
System.out.println("线程3执行了。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程3");
executorService.submit(t1);
executorService.submit(t2);
executorService.submit(t3);
}
打印结果
---开启线程1---
---开启线程2---
---开启线程3---
线程1执行了。。。
线程2执行了。。。
线程3执行了。。。
5.2、多线程化线程池
其实最常见的还是使用多线程化的线程池去实现。
private static ExecutorService executorService = Executors.newFixedThreadPool(3);
public static void main(String[] args) throws InterruptedException, ExecutionException {
long start = System.currentTimeMillis();
ArrayList<Future<String>> futureList = new ArrayList<Future<String>>();
ArrayList<String> names = new ArrayList<String>();
for (int i = 0; i < 3; i++) {
futureList.add(executorService.submit(new MyCall(i + "")));
}
for (int i = 0; i < 3; i++) {
Future<String> future = futureList.get(i);
String value = future.get();
System.out.println("线程"+value+"执行了");
}
long spendTime = System.currentTimeMillis() - start;
System.out.println("花费时间---"+spendTime);
}
static class MyCall implements Callable<String> {
private String name;
public MyCall(String name) {
this.name = name;
}
@Override
public String call() throws Exception {
switch (name){
case "0":
Thread.sleep(3000);
break;
case "1":
Thread.sleep(2000);
break;
case "2":
Thread.sleep(1000);
break;
}
return name;
}
}
打印结果
线程0执行了
线程1执行了
线程2执行了
花费时间---3006
常见的问题:
- 1、2、3总共3个线程,按顺序请求,按顺序取结果。
- 1、2、3总共3个线程,线程3要等到线程1和2执行完才能执行,线程1和2是并行的。
- 写一个多线程程序,交替输出1,2,1,2,1,2
相信上面的问题应该不难了。。