Java Thread 多线程使用示例
一、多线程创建方式1
package space.goldchen.demo.thread;
/**
* 一、测试多线程
* 继承Thread
*
* @author Goldchen
* @create 2022-11-12 16:03
*/
public class ExtendsThreadTest01 {
public static void main(String[] args) {
new ThreadJob().start();
//主线程循环打印
for (int i = 0; i < 10; i++) {
System.out.println("主线程正在执行" + i);
}
}
}
/**
* 继承Thread
*/
class ThreadJob extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("子线程正在执行" + i);
}
}
}
/*
主线程正在执行0
主线程正在执行1
主线程正在执行2
子线程正在执行0
主线程正在执行3
主线程正在执行4
主线程正在执行5
子线程正在执行1
主线程正在执行6
子线程正在执行2
主线程正在执行7
子线程正在执行3
主线程正在执行8
主线程正在执行9
子线程正在执行4
子线程正在执行5
子线程正在执行6
子线程正在执行7
子线程正在执行8
子线程正在执行9
*/
二、多线程创建方式2
package space.goldchen.demo.thread;
/**
* 二、实现接口,创建多线程
*
* @author Goldchen
* @create 2022-11-12 16:22
*/
public class ImplementsRunnableTest02 {
public static void main(String[] args) {
RunnableJop runnableJop = new RunnableJop();
Thread thread = new Thread(runnableJop);
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println(i + "主线程");
}
}
}
class RunnableJop implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("子线程" + i);
}
}
}
/*
输出:
0主线程
1主线程
2主线程
3主线程
4主线程
5主线程
6主线程
子线程0
子线程1
7主线程
子线程2
子线程3
子线程4
子线程5
子线程6
子线程7
子线程8
子线程9
8主线程
9主线程
*/
三、线程不安全示例
package space.goldchen.demo.thread;
/**
* 三、线程安全
* 安全不安全的例子:重复消费了第50张票
*
* @author Goldchen
* @create 2022-11-12 16:36
*/
public class TicketTest03 {
public static void main(String[] args) {
TicketJob ticketJob = new TicketJob();
Thread thread1 = new Thread(ticketJob, "窗口一");
Thread thread2 = new Thread(ticketJob, "窗口二");
Thread thread3 = new Thread(ticketJob, "窗口三");
thread1.start();
thread2.start();
thread3.start();
}
}
class TicketJob implements Runnable {
private int num = 50;
@Override
public void run() {
while (true) {
if (num > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name + ": 正在卖第" + num + "张票");
num--;
} else {
break;
}
}
}
}
/*
窗口三: 正在卖第50张票
窗口二: 正在卖第50张票
窗口一: 正在卖第50张票
窗口一: 正在卖第47张票
窗口三: 正在卖第47张票
窗口二: 正在卖第47张票
窗口二: 正在卖第44张票
窗口三: 正在卖第44张票
窗口一: 正在卖第44张票
窗口二: 正在卖第41张票
窗口一: 正在卖第41张票
窗口三: 正在卖第41张票
窗口三: 正在卖第38张票
窗口二: 正在卖第38张票
窗口一: 正在卖第38张票
窗口二: 正在卖第35张票
窗口一: 正在卖第35张票
窗口三: 正在卖第35张票
窗口二: 正在卖第32张票
窗口三: 正在卖第32张票
窗口一: 正在卖第32张票
窗口三: 正在卖第29张票
窗口一: 正在卖第29张票
窗口二: 正在卖第29张票
窗口一: 正在卖第26张票
窗口三: 正在卖第26张票
窗口二: 正在卖第26张票
窗口一: 正在卖第23张票
窗口三: 正在卖第23张票
窗口二: 正在卖第23张票
窗口一: 正在卖第20张票
窗口三: 正在卖第20张票
窗口二: 正在卖第20张票
窗口二: 正在卖第17张票
窗口三: 正在卖第17张票
窗口一: 正在卖第17张票
窗口三: 正在卖第14张票
窗口一: 正在卖第14张票
窗口二: 正在卖第14张票
窗口三: 正在卖第11张票
窗口一: 正在卖第11张票
窗口二: 正在卖第11张票
窗口二: 正在卖第8张票
窗口三: 正在卖第8张票
窗口一: 正在卖第8张票
窗口二: 正在卖第5张票
窗口一: 正在卖第5张票
窗口三: 正在卖第5张票
窗口二: 正在卖第2张票
窗口三: 正在卖第2张票
窗口一: 正在卖第2张票
窗口二: 正在卖第-1张票
*/
四、线程安全,方式1
package space.goldchen.demo.thread;
/**
* 四、使用synchronized同步代码块
* 线程安全的:使用synchronized同步代码块 同步锁,就不会重复消费了
*
* @author Goldchen
* @create 2022-11-12 17:06
*/
public class TickerSafeTest04 {
public static void main(String[] args) {
TicketSafeJob ticketSafeJob = new TicketSafeJob();
Thread thread1 = new Thread(ticketSafeJob, "窗口一");
Thread thread2 = new Thread(ticketSafeJob, "窗口二");
Thread thread3 = new Thread(ticketSafeJob, "窗口三");
thread1.start();
thread2.start();
thread3.start();
}
}
class TicketSafeJob implements Runnable {
private int num = 50;
Object lockObject = new Object();
@Override
public void run() {
while (true) {
synchronized (lockObject) {
if (num > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name + ": 正在卖第" + num + "张票");
num--;
} else {
break;
}
}
}
}
}
/*
窗口一: 正在卖第50张票
窗口一: 正在卖第49张票
窗口一: 正在卖第48张票
窗口一: 正在卖第47张票
窗口一: 正在卖第46张票
窗口一: 正在卖第45张票
窗口二: 正在卖第44张票
窗口二: 正在卖第43张票
窗口二: 正在卖第42张票
窗口二: 正在卖第41张票
窗口二: 正在卖第40张票
窗口二: 正在卖第39张票
窗口二: 正在卖第38张票
窗口二: 正在卖第37张票
窗口二: 正在卖第36张票
窗口二: 正在卖第35张票
窗口二: 正在卖第34张票
窗口二: 正在卖第33张票
窗口二: 正在卖第32张票
窗口二: 正在卖第31张票
窗口二: 正在卖第30张票
窗口二: 正在卖第29张票
窗口二: 正在卖第28张票
窗口二: 正在卖第27张票
窗口二: 正在卖第26张票
窗口二: 正在卖第25张票
窗口二: 正在卖第24张票
窗口二: 正在卖第23张票
窗口二: 正在卖第22张票
窗口二: 正在卖第21张票
窗口二: 正在卖第20张票
窗口二: 正在卖第19张票
窗口二: 正在卖第18张票
窗口二: 正在卖第17张票
窗口二: 正在卖第16张票
窗口二: 正在卖第15张票
窗口二: 正在卖第14张票
窗口二: 正在卖第13张票
窗口二: 正在卖第12张票
窗口二: 正在卖第11张票
窗口二: 正在卖第10张票
窗口二: 正在卖第9张票
窗口二: 正在卖第8张票
窗口二: 正在卖第7张票
窗口二: 正在卖第6张票
窗口二: 正在卖第5张票
窗口二: 正在卖第4张票
窗口二: 正在卖第3张票
窗口二: 正在卖第2张票
窗口二: 正在卖第1张票
*/
五、线程安全,方式2
package space.goldchen.demo.thread;
/**
* 五、使用同步锁方法
* 线程安全的:使用synchronized修饰方法 同步锁,就不会重复消费了
*
* @author Goldchen
* @create 2022-11-12 17:06
*/
public class TickerSafeMethodTest05 {
public static void main(String[] args) {
TicketSafeMethodJob ticketSafeMethodJob = new TicketSafeMethodJob();
Thread thread1 = new Thread(ticketSafeMethodJob, "窗口一");
Thread thread2 = new Thread(ticketSafeMethodJob, "窗口二");
Thread thread3 = new Thread(ticketSafeMethodJob, "窗口三");
thread1.start();
thread2.start();
thread3.start();
}
}
class TicketSafeMethodJob implements Runnable {
private int num = 50;
@Override
public void run() {
while (true) {
ticketSafeMethod();
if(num==0){
break;
}
}
}
/**
* synchronized 同步方法锁
*/
private synchronized void ticketSafeMethod() {
if (num > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name + ": 正在卖第" + num + "张票");
num--;
}
}
}
/*
窗口一: 正在卖第50张票
窗口一: 正在卖第49张票
窗口一: 正在卖第48张票
窗口一: 正在卖第47张票
窗口一: 正在卖第46张票
窗口一: 正在卖第45张票
窗口一: 正在卖第44张票
窗口一: 正在卖第43张票
窗口一: 正在卖第42张票
窗口一: 正在卖第41张票
窗口一: 正在卖第40张票
窗口一: 正在卖第39张票
窗口一: 正在卖第38张票
窗口一: 正在卖第37张票
窗口一: 正在卖第36张票
窗口一: 正在卖第35张票
窗口一: 正在卖第34张票
窗口一: 正在卖第33张票
窗口一: 正在卖第32张票
窗口一: 正在卖第31张票
窗口一: 正在卖第30张票
窗口一: 正在卖第29张票
窗口一: 正在卖第28张票
窗口一: 正在卖第27张票
窗口一: 正在卖第26张票
窗口一: 正在卖第25张票
窗口一: 正在卖第24张票
窗口一: 正在卖第23张票
窗口一: 正在卖第22张票
窗口一: 正在卖第21张票
窗口一: 正在卖第20张票
窗口三: 正在卖第19张票
窗口三: 正在卖第18张票
窗口三: 正在卖第17张票
窗口三: 正在卖第16张票
窗口三: 正在卖第15张票
窗口三: 正在卖第14张票
窗口三: 正在卖第13张票
窗口三: 正在卖第12张票
窗口三: 正在卖第11张票
窗口三: 正在卖第10张票
窗口三: 正在卖第9张票
窗口三: 正在卖第8张票
窗口三: 正在卖第7张票
窗口三: 正在卖第6张票
窗口三: 正在卖第5张票
窗口三: 正在卖第4张票
窗口三: 正在卖第3张票
窗口三: 正在卖第2张票
窗口三: 正在卖第1张票
*/
六、线程安全,方式3
package space.goldchen.demo.thread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 六、使用Lock锁
* 线程安全的:使用Lock lock = new ReentrantLock();
* 就不会重复消费了
*
* @author Goldchen
* @create 2022-11-12 17:06
*/
public class TickerSafeLockTest06 {
public static void main(String[] args) {
TicketSafeLockJob ticketSafeLockJob = new TicketSafeLockJob();
Thread thread1 = new Thread(ticketSafeLockJob, "窗口一");
Thread thread2 = new Thread(ticketSafeLockJob, "窗口二");
Thread thread3 = new Thread(ticketSafeLockJob, "窗口三");
thread1.start();
thread2.start();
thread3.start();
}
}
class TicketSafeLockJob implements Runnable {
private int num = 50;
Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
// lock.lock()
lock.lock();
if (num > 0) {
try {
Thread.sleep(10);
String name = Thread.currentThread().getName();
System.out.println(name + "正在卖第:" + num + "张票");
num--;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// lock.unlock();
lock.unlock();
}
} else {
lock.unlock();
return;
}
}
}
}
/*
窗口一正在卖第:50张票
窗口一正在卖第:49张票
窗口一正在卖第:48张票
窗口二正在卖第:47张票
窗口二正在卖第:46张票
窗口二正在卖第:45张票
窗口二正在卖第:44张票
窗口二正在卖第:43张票
窗口二正在卖第:42张票
窗口二正在卖第:41张票
窗口二正在卖第:40张票
窗口二正在卖第:39张票
窗口二正在卖第:38张票
窗口二正在卖第:37张票
窗口二正在卖第:36张票
窗口二正在卖第:35张票
窗口二正在卖第:34张票
窗口二正在卖第:33张票
窗口二正在卖第:32张票
窗口二正在卖第:31张票
窗口二正在卖第:30张票
窗口二正在卖第:29张票
窗口二正在卖第:28张票
窗口二正在卖第:27张票
窗口二正在卖第:26张票
窗口二正在卖第:25张票
窗口二正在卖第:24张票
窗口二正在卖第:23张票
窗口三正在卖第:22张票
窗口三正在卖第:21张票
窗口三正在卖第:20张票
窗口三正在卖第:19张票
窗口三正在卖第:18张票
窗口三正在卖第:17张票
窗口三正在卖第:16张票
窗口三正在卖第:15张票
窗口三正在卖第:14张票
窗口三正在卖第:13张票
窗口三正在卖第:12张票
窗口三正在卖第:11张票
窗口三正在卖第:10张票
窗口三正在卖第:9张票
窗口三正在卖第:8张票
窗口三正在卖第:7张票
窗口三正在卖第:6张票
窗口三正在卖第:5张票
窗口三正在卖第:4张票
窗口三正在卖第:3张票
窗口三正在卖第:2张票
窗口三正在卖第:1张票
*/
七、线程池使用示例
package space.goldchen.demo.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 七、线程池 使用
*
* @author Goldchen
* @create 2022-11-12 22:17
*/
public class ThreadPollTest07 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(4);
ThreadPoolJob threadPoolJob = new ThreadPoolJob();
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.submit(threadPoolJob);
executorService.shutdown();
}
}
/**
* 实现Runnable的 线程任务
*/
class ThreadPoolJob implements Runnable {
@Override
public void run() {
System.out.println("当前线程为:" + Thread.currentThread().getName());
}
}
/*
当前线程为:pool-1-thread-1
当前线程为:pool-1-thread-4
当前线程为:pool-1-thread-3
当前线程为:pool-1-thread-4
当前线程为:pool-1-thread-1
当前线程为:pool-1-thread-3
当前线程为:pool-1-thread-2
当前线程为:pool-1-thread-3
当前线程为:pool-1-thread-4
当前线程为:pool-1-thread-1
当前线程为:pool-1-thread-2
*/