多线程编程例子
本博文记录多线程编程的几个案例,包含了常见的几种多线程编程套路。
1.四个线程计算1到100的求和
1.依次调用thread.join(),主线程输出结果。注意:sum为共享变量,访问共享变量时,用synchronized同步
public class ThreadTest {
private static Object LOCK = new Object();
private static int sum = 0;
public static void main(String[] args) throws InterruptedException {
ThreadTest threadTest = new ThreadTest();
Thread t1 = threadTest.new ThreadSum(1,25);
Thread t2 = threadTest.new ThreadSum(26,50);
Thread t3 = threadTest.new ThreadSum(51,75);
Thread t4 = threadTest.new ThreadSum(76,100);
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println("totalSum: " + sum);
}
class ThreadSum extends Thread{
private int begin;
private int end;
public ThreadSum(int begin, int end){
this.begin = begin;
this.end = end;
}
@Override
public void run() {
try {
Thread.sleep(100);//便于测试
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (LOCK){
for(int i=begin; i<=end; ++i){
sum += i;
}
System.out.println(Thread.currentThread().getName() + ": " + sum);
}
}
}
}
out:Thread-1: 950
Thread-0: 1275
Thread-3: 3475
Thread-2: 5050
totalSum: 5050
2.子线程执行完调用countdownlatch.countdown(),主线程调用countdownlatc.await() 等待子线程执行完成,输出结果。 注意:sum为共享变量,访问共享变量时,用synchronized同步
public class ThreadTest {
private static Object LOCK = new Object();
private static int sum = 0;
private static CountDownLatch countDownLatch = new CountDownLatch(4);
public static void main(String[] args) throws InterruptedException {
ThreadTest threadTest = new ThreadTest();
Thread t1 = threadTest.new ThreadSum(1,25);
Thread t2 = threadTest.new ThreadSum(26,50);
Thread t3 = threadTest.new ThreadSum(51,75);
Thread t4 = threadTest.new ThreadSum(76,100);
t1.start();
t2.start();
t3.start();
t4.start();
countDownLatch.await();
System.out.println("totalSum: " + sum);
}
class ThreadSum extends Thread{
private int begin;
private int end;
public ThreadSum(int begin, int end){
this.begin = begin;
this.end = end;
}
@Override
public void run() {
try {
Thread.sleep(100);//便于测试
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (LOCK){
for(int i=begin; i<=end; ++i){
sum += i;
}
System.out.println(Thread.currentThread().getName() + ": " + sum);
}
countDownLatch.countDown();
}
}
}
3.线程池
public class ThreadTest {
private static Object LOCK = new Object();
private static int sum = 0;
private static CountDownLatch countDownLatch = new CountDownLatch(4);
public static void main(String[] args) throws InterruptedException {
ThreadTest threadTest = new ThreadTest();
ExecutorService pool = Executors.newFixedThreadPool(4);
for(int i=1; i<=76; i+=25){
pool.execute(threadTest.new ThreadSum(i, i+24));
}
countDownLatch.await();
pool.shutdown();
System.out.println("totalSum: " + sum);
}
class ThreadSum extends Thread{
private int begin;
private int end;
public ThreadSum(int begin, int end){
this.begin = begin;
this.end = end;
}
@Override
public void run() {
try {
Thread.sleep(100);//便于测试
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (LOCK){
for(int i=begin; i<=end; ++i){
sum += i;
}
System.out.println(Thread.currentThread().getName() + ": " + sum);
}
countDownLatch.countDown();
}
}
}
4.使用ExecutorService、Callable、Future实现有返回结果的线程
public class ThreadTest {
private static List<Future> futureList = new ArrayList<>();
public static void main(String[] args) throws InterruptedException, ExecutionException {
ThreadTest threadTest = new ThreadTest();
ExecutorService pool = Executors.newFixedThreadPool(4);
for(int i=1; i<=76; i+=25){
ThreadCallSum threadCallSum = threadTest.new ThreadCallSum(i, i+24);
Future future = pool.submit(threadCallSum);
futureList.add(future);
}
pool.shutdown();
int sum = 0;
for(Future<Integer> future: futureList){
sum += future.get();
}
System.out.println("totalSum: " + sum);
}
class ThreadCallSum implements Callable<Integer>{
private int begin;
private int end;
private int sum = 0;
public ThreadCallSum(int begin, int end){
this.begin = begin;
this.end = end;
}
@Override
public Integer call() throws InterruptedException {
Thread.sleep(100);
for(int i=begin; i<=end; ++i){
sum += i;
}
System.out.println(Thread.currentThread().getName() + ": " + sum);
return sum;
}
}
}
out:
pool-1-thread-2: 950
pool-1-thread-4: 2200
pool-1-thread-1: 325
pool-1-thread-3: 1575
totalSum: 5050
2.三个线程打印一个1-100的数组,要求P1=1,P2=2,P3=3,P1=4的形式
public class ThreadTest {
private static volatile int count = 1;
private static Object object = new Object();
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
ExecutorService pool = Executors.newFixedThreadPool(3);
while (count <= 100) {
pool.execute(threadTest.new ThreadCnt());
}
pool.shutdown();
}
class ThreadCnt extends Thread {
public void run() {
if(count<=100) {
synchronized (object) {
if (count % 3 == 1 && Thread.currentThread().getName().contains("thread-1")) {
System.out.println(Thread.currentThread().getName() + ": " + count);
count++;
} else if (count % 3 == 2 && Thread.currentThread().getName().contains("thread-2")) {
System.out.println(Thread.currentThread().getName() + ": " + count);
count++;
} else if (count % 3 == 0 && Thread.currentThread().getName().contains("thread-3")) {
System.out.println(Thread.currentThread().getName() + ": " + count);
count++;
}
}
}
}
}
}
out:
pool-1-thread-1: 1
pool-1-thread-2: 2
pool-1-thread-3: 3
pool-1-thread-1: 4
pool-1-thread-2: 5
3.java多线程(2个线程)交替打印0-100的奇偶数
用到了notify、wait机制
public class ThreadTest extends Thread{
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
Thread t1 = threadTest.new ThreadOdd();
Thread t2 = threadTest.new ThreadEven();
t1.start();
t2.start();
}
private synchronized void print(String str ,int i){
notify();
System.out.println(str + ": " + i);
try {
if(i==100){//100次的时候要唤醒全部,否则循环结束不了
notifyAll();
}
else{
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
class ThreadOdd extends Thread{
public void run(){
for(int i=1; i<=100; i+=2){
print(Thread.currentThread().getName(), i);
}
}
}
class ThreadEven extends Thread{
public void run(){
for(int i=2; i<=100; i+=2){
print(Thread.currentThread().getName(), i);
}
}
}
}
out:
...
t1: 97
t2: 98
t1: 99
t2: 100
4.三个线程循环打印1-100,每个线程每次打印3个数
1.用线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class ThreadTest{
private static volatile int count = 1;
private static volatile int threadCnt = 1;
private static Object object = new Object();
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
ExecutorService pool = Executors.newFixedThreadPool(3);
while(count<=100){
pool.execute(threadTest.new ThreadCnt());
}
pool.shutdown();
}
class ThreadCnt extends Thread{
public void print(){
System.out.print(Thread.currentThread().getName() + ":");
int k = 3;
while(count<=100 && k!=0){
System.out.print(" " + count);
count++;
k--;
}
System.out.println();
threadCnt++;
}
public void run(){
if(count<=100) {
synchronized (object) {
if(count<=100) {//double-check
if (threadCnt % 3 == 1 && Thread.currentThread().getName().contains("thread-1")) {
print();
} else if (threadCnt % 3 == 2 && Thread.currentThread().getName().contains("thread-2")) {
print();
} else if (threadCnt % 3 == 0 && Thread.currentThread().getName().contains("thread-3")) {
print();
}
}
}
}
}
}
}
2.用notify、wait–>这个注释的很好,强推看代码!!
class ThreadTest{
private static volatile int count = 1;//打印的count
private static volatile int countC = 0;//线程计数:保证依次打印的顺序
private static Object object = new Object();
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
Thread t1 = threadTest.new ThreadCnt(0);//每个线程分配id号,便于依次打印时与countC比较
Thread t2 = threadTest.new ThreadCnt(1);
Thread t3 = threadTest.new ThreadCnt(2);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
class ThreadCnt extends Thread{//这里的ThreadCnt类前加不加static都可以,因为锁的是ThreadCnt.class!!
private int id;
public ThreadCnt(int id){
this.id = id;
}
public void run(){
while(count<=100){
synchronized (object){//这里锁ThreadCnt.class、ThreadTest.class、object都可以!!
if(count<=100) {//double-check
if (countC % 3 == id) {//通过id保证线程依次打印
object.notifyAll();//这里的notifyAll()、wait()的object类对象必须与上面的synchronized里的对象保持一致!!
System.out.print(Thread.currentThread().getName() + ":");
int k = 3;
while (count <= 100 && k != 0) {
System.out.print(" " + count);
count++;
k--;
}
System.out.println();
countC++;
}
else{
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
5.java实现生产者消费者模式
1.notify/wait实现
import java.util.LinkedList;
import java.util.Queue;
/**
* @FileName: ProAndCus
* @Author: braincao
* @Date: 2019/3/21 14:39
* @Description: java实现生产者消费者模式(notify/wait实现)
*/
public class ProAndCus {
private Queue<Integer> queue = new LinkedList<>();
private int queMaxLen = 10;
private static Object object = new Object();
private static volatile int dataCnt = 0;//生产的物品,为了测试,这里规定生产者最多能生产10个(1-10)
public static void main(String[] args) {
ProAndCus proAndCus = new ProAndCus();
Thread p1 = proAndCus.new Pro();
Thread p2 = proAndCus.new Pro();
Thread p3 = proAndCus.new Pro();
Thread p4 = proAndCus.new Pro();
Thread c1 = proAndCus.new Cus();
Thread c2 = proAndCus.new Cus();
Thread c3 = proAndCus.new Cus();
Thread c4 = proAndCus.new Cus();
p1.setName("p1--");
p2.setName("p2--");
p3.setName("p3--");
p4.setName("p4--");
c1.setName("c1--");
c2.setName("c2--");
c3.setName("c3--");
c4.setName("c4--");
p1.start();
p2.start();
p3.start();
p4.start();
c1.start();
c2.start();
c3.start();
c4.start();
}
class Pro extends Thread{
public void run(){
try {
while (dataCnt<10) {
Thread.sleep(100);
synchronized (object) {
if (queue.size() >= queMaxLen) {
object.wait();
}
if(dataCnt<10){
dataCnt++;
queue.offer(dataCnt);
System.out.println(Thread.currentThread().getName() + "生产:" + dataCnt);
}
object.notifyAll();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
class Cus extends Thread{
public void run(){
try {
while (true) {
Thread.sleep(100);
synchronized (object) {
if(queue.isEmpty()) {
if(dataCnt<10){
object.wait();
}
else{
break;
}
}
else{
System.out.println(Thread.currentThread().getName() + "消费:" + queue.poll());
}
object.notifyAll();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
2.阻塞队列实现
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
//使用阻塞队列BlockingQueue解决生产者消费者
public class BlockingQueueConsumerProducer {
private static volatile int dataCnt = 0;
private static BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(10);
public static void main(String[] args) {
BlockingQueueConsumerProducer cp = new BlockingQueueConsumerProducer();
//生产者线程
Pro p1 = cp.new Pro();
Pro p2 = cp.new Pro();
p1.setName("p1");
p2.setName("p2");
//消费者线程
Cus c1 = cp.new Cus();
Cus c2 = cp.new Cus();
Cus c3 = cp.new Cus();
Cus c4 = cp.new Cus();
Cus c5 = cp.new Cus();
c1.setName("c1");
c2.setName("c2");
c3.setName("c3");
c4.setName("c4");
c5.setName("c5");
p1.start();
p2.start();
c1.start();
c2.start();
c3.start();
c4.start();
c5.start();
}
/**
* 消费者线程
* @author tangzhijing
*
*/
class Cus extends Thread {
public void run() {
try {
while (true) {
Thread.sleep((long) (1000 * Math.random()));
if(!blockingQueue.isEmpty()){
System.out.println(Thread.currentThread().getName() + "消费了:" + blockingQueue.poll());
}
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
/**
* 生产者线程
* @author tangzhijing
*
*/
class Pro extends Thread{
public void run() {
try {
while (true) {
Thread.sleep((long) (1000 * Math.random()));
dataCnt++;
blockingQueue.offer(dataCnt);
System.out.println(Thread.currentThread().getName() + "生产了:" + dataCnt);
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
}
6.猴子偷桃抢着进行
一个拿2个,一个拿3个,共有9个
public class Apple {
public static volatile int clientTotal = 9;//共有9个苹果
//同时并发执行的线程数:两个猴子各一个线程
public static void main(String[] args){
Thread monkeyOne = new Thread(new Runnable() {
@Override
public void run() {
while(clientTotal>=2){
synchronized (Apple.class) {
if (clientTotal >= 2) {//double-check
clientTotal -= 2;
System.out.println("A猴子拿了2个,还剩:" + clientTotal + "个");
}
}
try {
Thread.sleep(100);//为了测试期间,这里加个sleep
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread monkeyTwo = new Thread(new Runnable() {
@Override
public void run() {
while(clientTotal>=3){
synchronized (Apple.class) {
if (clientTotal >= 3) {
clientTotal -= 3;
System.out.println("B猴子拿了3个,还剩:" + clientTotal + "个");
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
monkeyOne.start();
monkeyTwo.start();
}
}
6.猴子偷桃交替进行
public class Apple {
public static volatile int clientTotal = 9;//共有9个苹果
public static Object object = new Object();
//同时并发执行的线程数:两个猴子各一个线程
public static void main(String[] args){
Apple apple = new Apple();
Thread t1 = apple.new ThreadMOne();
Thread t2 = apple.new ThreadMTwo();
t1.start();
t2.start();
}
class ThreadMOne extends Thread{
public void run(){
try {
while(clientTotal>=2){
Thread.sleep(100);
synchronized (object) {
object.notify();
if(clientTotal<2){
break;
}
clientTotal -= 2;
System.out.println("A猴子拿了2个,还剩:" + clientTotal + "个");
if(clientTotal<3){
break;
}
object.wait();
}
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
class ThreadMTwo extends Thread{
public void run(){
try {
while(clientTotal>=3){
Thread.sleep(100);
synchronized (object) {
object.notify();
if(clientTotal<3){
break;
}
clientTotal -= 3;
System.out.println("B猴子拿了3个,还剩:" + clientTotal + "个");
if(clientTotal<3){
break;
}
object.wait();
}
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
}
out:
A猴子拿了2个,还剩:7个
B猴子拿了3个,还剩:4个
A猴子拿了2个,还剩:2个
欢迎转载,欢迎错误指正与技术交流,欢迎交友谈心
文章标题:多线程编程例子
文章字数:2.4k
本文作者:Brain Cao
发布时间:2019-10-01, 19:00:08
最后更新:2020-02-27, 19:04:06
原始链接:https://braincao.cn/2019/10/01/multithread-programming-demo/版权声明:本文为博主原创文章,遵循 BY-NC-SA 4.0 版权协议,转载请保留原文链接与作者。