- 三个线程t1、t2、t3。确保三个线程,t1执行完后t2执行,t2执行完后t3执行。
使用Semaphore
- 三个线程t1、t2、t3。确保三个线程,t1,t2执行完,t3再执行。
public class Test01 {
private Object obj = new Object();
//线程1、2执行完后,再执行线程3,使用wait()、notify()
public static void main(String[] args) {
new Test01().exec();
}
public void exec(){
new Thread(()->{
synchronized (obj){
try {
obj.wait();
System.out.println("线程:"+Thread.currentThread().getName()+"=>执行了....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},String.valueOf(3)).start();
for (int i = 0; i < 2; i++) {
final int tmp = i;
new Thread(()->{
synchronized (obj){
System.out.println("线程:" + Thread.currentThread().getName() + "=>执行了....");
if(tmp == 1)
obj.notify();
}
},String.valueOf(i+1)).start();
}
}
}
public class Test02 {
private CountDownLatch latch =new CountDownLatch(2);
//线程1、2执行完后,再执行线程3,使用CountDownLatch
public static void main(String[] args) {
new Test02().exec();
}
public void exec(){
new Thread(()->{
try {
latch.await();
System.out.println(Thread.currentThread().getName() + "=>执行了....");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"线程3").start();
for (int i = 0; i < 2; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "=>执行了....");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
},String.valueOf("线程" + (i+1))).start();
}
}
}
class T1 implements Runnable{
@Override
public void run() {
System.out.println("1");
}
}
class T2 implements Runnable{
Thread father;
public void set(Thread father) {
this.father = father;
}
@Override
public void run() {
try {
father.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("2");
}
}
class T3 implements Runnable{
Thread father;
public void set(Thread father) {
this.father = father;
}
@Override
public void run() {
try {
father.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("3");
}
}
public class Test {
//使用join
public static void main(String[] args) {
T1 task1 = new T1();
T2 task2 = new T2();
T3 task3 = new T3();
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
Thread t3 = new Thread(task3);
task2.set(t1);
task3.set(t1);
t1.start();
t2.start();
t3.start();
}
}
- 现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象。
public class Test {
/**
* 现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,
* 请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象;
* 思路1:
* 1.将16个日志对象放到阻塞队列中
* 2.开启4个线程从阻塞队列中拿日志对象执行
* 3.日志对象执行时间为 1s
* 4.此方式线程会一直跑,阻塞
*
* 思路2:
* 1.创建具有4个核心线程的线程池
* 2.在阻塞队列中加入16个打印日志对象的任务
* 3.执行线程池的任务
* 4.日志对象执行时间为 1s
* 5.此方式线程会销毁
*
*/
public static void main(String[] args) {
test01(); //思路1实现
//test02(); //思路2实现
}
private static void test01() {
long start = System.currentTimeMillis();
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(16);
//将16个日志对象放入阻塞队列中
for (int i = 1; i <= 16; i++) {
try {
queue.put("日志对象:" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//开启4个线程从阻塞队列中拿日志对象执行
for (int i = 0; i < 4; i++) {
new Thread(()->{
while(true){
try {
String log = queue.take();
printLog(log);
long end = System.currentTimeMillis();
System.out.println((end-start) + "ms");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
public static void test02(){
long start = System.currentTimeMillis();
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(16);
//创建具有四个核心线程的线程池
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
4,
4,
3000,
TimeUnit.MILLISECONDS,
queue,
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
//将16个打印日志对象的任务放入阻塞队列中
for (int i = 0; i < 16; i++) {
final String tmp = "任务" + (i+1) + "";
poolExecutor.execute(()->{
printLog(tmp);
});
}
poolExecutor.shutdown();
//判断线程池的任务是否执行完毕
while(true){
long end = System.currentTimeMillis();
if(poolExecutor.isTerminated()){
System.out.println((end-start) + "ms");
break;
}
}
}
public static void printLog(String log){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "===>打印日志=========>" + log);
}
}
- 10个线程同步执行10个任务
public class Test2 {
/**
* 10个线程同步执行10个任务
* 方式1:synchronized
* 方式2:Lock
* 方式3:Semaphore
* @param args
*/
public static void main(String[] args) {
//test01(); //synchronized
//test02(); //Lock
test03(); //Semaphore
}
public static void test01(){
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);
//往阻塞队列中加入任务
for (int i = 0; i < 10; i++) {
try {
queue.put("任务:" + (i+1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//10个线程顺序执行任务
for (int i = 0; i < 10; i++) {
new Thread(()->{
synchronized (queue){
try {
String task = queue.take();
executeTask(task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
public static void test02(){
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
Lock lock = new ReentrantLock();
//往阻塞队列中加入任务
for (int i = 0; i < 10; i++) {
try {
queue.put("任务:" + (i+1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//10个线程顺序执行任务
for (int i = 0; i < 10; i++) {
new Thread(()->{
try {
lock.lock();
String task = queue.take();
executeTask(task);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}).start();
}
}
public static void test03(){
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);
Semaphore semaphore = new Semaphore(1);
//往阻塞队列中加入任务
for (int i = 0; i < 10; i++) {
try {
queue.put("任务:" + (i+1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//10个线程顺序执行任务
for (int i = 0; i < 10; i++) {
new Thread(()->{
try {
semaphore.acquire();
String task = queue.take();
executeTask(task);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
public static void executeTask(String task){
System.out.println(Thread.currentThread().getName() + "==>" + task);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 10个商品被20个用户抢购,如何让商品正常卖出,不会超卖:
public class Test03 {
//10个商品
private int goods = 10;
public static void main(String[] args) {
new Test03().exec();
}
public synchronized void exec(){
for (int i = 0; i < 20; i++) {
new Thread(()->{
if(goods > 0){
System.out.println(Thread.currentThread().getName() + ",抢到了第 " + goods-- + " 张票");
}
},String.valueOf("用户" + (i+1))).start();
}
}
}
- 生产者消费者问题
//数据
class Data{
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
//生产者
class Producer implements Runnable{
private Data data;
public Producer(Data data) {
this.data = data;
}
@Override
public void run() {
int i = 0;
while(true) {
synchronized(data){
//如果数据为空,则生产数据
if(data.getMessage() == null) {
data.setMessage(i + "");
System.out.println("生产:" + i);
i++;
}
//生产完数据通知消费者消费
data.notify();
//生产者挂起
try {
data.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
//消费者
class Consumer implements Runnable{
private Data data;
public Consumer(Data data) {
this.data = data;
}
public void run() {
while(true) {
synchronized(data) {
//如果数据不为空,则消费
if(data.getMessage() != null) {
System.out.println("消费:" + data.getMessage());
data.setMessage(null);
}
//消费完,通知生产者进行生产
data.notify();
//消费者挂起
try {
data.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Test {
public static void main(String[] args) {
Data data = new Data();
Producer p = new Producer(data);
Consumer c = new Consumer(data);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}
- 优雅的停止线程
class Task implements Runnable{
private volatile boolean isFlag = true;
public void stop() {
this.isFlag = false;
}
public void run() {
int i = 0;
while(isFlag) {
System.out.println(i++);
}
}
}
public class Test {
//使用标志位
public static void main(String[] args) throws InterruptedException {
Task task = new Task();
Thread t = new Thread(task);
t.start();
TimeUnit.SECONDS.sleep(1);
task.stop();
}
}
class Task implements Runnable{
public void run() {
int i = 0;
while(true) {
Thread t = Thread.currentThread();
if(t.isInterrupted()) { //判断是否处于中断状态
break;
}
System.out.println(i++);
}
}
}
public class Test {
//使用interrupt
public static void main(String[] args) throws InterruptedException {
Task task = new Task();
Thread t = new Thread(task);
t.start();
TimeUnit.SECONDS.sleep(1);
t.interrupt(); //中断
}
}
- 多线程循环顺序打印:ABABABABAB,线程A打印A,线程B打印B。
使用Object.wait()和notifyAll() 或者Lock + Condition
- 多线程循环顺序打印:0102030405,线程0打印0,线程1打印奇数,线程2打印偶数
使用Object.wait()和notifyAll() 或者Lock + Condition
代码后续更新。。。
shutdown和shutwdown的区别:
- shutdown只是将线程池的状态设置为SHUTWDOWN状态,正在执行的任务会继续执行下去,没有被执行的则中断。
- shutdownNow则是将线程池的状态设置为STOP,正在执行的任务则被停止,没被执行任务的则返回。
isShutDown:
- isShutDown当调用shutdown()或shutdownNow()方法后返回为true。
- isTerminated当调用shutdown()方法后,并且所有提交的任务完成后返回为true;
- isTerminated当调用shutdownNow()方法后,成功停止后返回为true;