本文章主要通过编码形式实现简单的多线程入门实例
1
/** * a 线程睡眠10毫秒 对变量加1 * b 线程睡眠20毫秒 对变量加1 * 持续60毫秒 * 分析:理论上a 线程应该打印6次 b线程应该打印3次 * 思路:通过变量来做累加 */
package com.thread.base; /** * a 线程睡眠10毫秒 对变量加1 * b 线程睡眠20毫秒 对变量加1 * 持续60毫秒 * 分析:理论上a 线程应该打印6次 b线程应该打印3次 * 思路:通过变量来做累加 */ @SuppressWarnings("all") public class Thread01 { static int num=0; static int b=0; public static void main(String[] args)throws Exception { Runnable r1 = new Runnable() { @Override public void run() { num++; System.out.println("r1:"+num); } }; Runnable r2 = new Runnable() { @Override public void run() { num++; System.out.println("r2:"+num); } }; while(true){ Thread.sleep(10); if(b%2==0)new Thread(r2).start(); new Thread(r1).start(); b++; if(b==6)break; } } }
2
/** * 启动3个线程: * 线程1 打印 1 2 3 4 5 * 线程2 打印 6 7 8 9 10 * 线程3 打印 11 12 13 14 15 * 依次循环 输出到75 * * 思路:使用一个可见变量 做累加让其它线程都能知道 */
package com.thread.base; /** * 启动3个线程: * 线程1 打印 1 2 3 4 5 * 线程2 打印 6 7 8 9 10 * 线程3 打印 11 12 13 14 15 * 依次循环 输出到75 * * 思路:使用一个可见变量 做累加让其它线程都能知道 */ public class Thread02 { public static void main(String[] args)throws Exception { new Thread(new MyRunnable(1)).start(); new Thread(new MyRunnable(2)).start(); new Thread(new MyRunnable(3)).start(); } } class MyRunnable implements Runnable{ int threadId; static volatile int num=0; public MyRunnable(int thredId){ this.threadId = thredId; } @Override public void run() { while(num<75){ synchronized (Thread02.class) { if(num/5%3 +1 ==threadId){ for (int i = 0; i <5; i++) { System.out.println("线程"+threadId+":"+(++num)); } Thread02.class.notifyAll(); } else{ try{ Thread02.class.wait(); } catch(Exception e){ e.printStackTrace(); } } } } } }
3
/** * 启动3个线程 * 线程1 每一次输入a * 线程2 每一次输入b * 线程3 每一次输入c * 连续3次 要求结果输入是abcabcabc这种连续的 * * 分析:其实是多个线程之间的同步,线程a执行完了才可以执行线程b,b执行完了再可以执行c * 线程执行顺序:a<b<c * 思路:可以使用一个可见状态变量来作为线程同步的标识 */
package com.thread.base; /** * 启动3个线程 * 线程1 每一次输入a * 线程2 每一次输入b * 线程3 每一次输入c * 连续3次 要求结果输入是abcabcabc这种连续的 * * 分析:其实是多个线程之间的同步,线程a执行完了才可以执行线程b,b执行完了再可以执行c * 线程执行顺序:a<b<c * 思路:可以使用一个可见状态变量来作为线程同步的标识 */ public class Thread03 { public static void main(String[] args)throws Exception { Object lock = new Object(); new Thread(new Run03able(0, 1, lock, "A")).start(); Thread.sleep(400); new Thread(new Run03able(1, 2, lock, "B")).start(); Thread.sleep(400); new Thread(new Run03able(2, 0, lock, "C")).start(); } } class Run03able implements Runnable { static volatile int state = 0;//可见状态 int printFlag;//当前打印的线程标识 int nextPrintFalg;//下一个可以打印的线程标识 Object obj;//锁对象 String printStr;//打印字符串 int count= 3; public Run03able(int printFalg,int nextPrintFalg,Object obj,String printStr){ this.nextPrintFalg = nextPrintFalg; this.printFlag = printFalg; this.obj = obj; this.printStr = printStr; } @Override public void run() { synchronized (Run03able.class) { for (int i = 0; i < count; i++) { while (state!=printFlag) { try { Run03able.class.wait(); } catch (InterruptedException e) { return; } } System.out.print(printStr); state = nextPrintFalg; Run03able.class.notifyAll(); } } } }
4
/** * 启动2个线程 * 线程a 打印 1 3 5 7 9 * 线程b 打印 2 4 6 8 10 * 分析:线程a打印的是奇数 线程b打印的是偶数 */
package com.thread.base; /** * 启动2个线程 * 线程a 打印 1 3 5 7 9 * 线程b 打印 2 4 6 8 10 * 分析:线程a打印的是奇数 线程b打印的是偶数 */ public class Thread04 { public static void main(String[] args) { new Thread(new PrintRunable("a")).start(); new Thread(new PrintRunable("b")).start(); } } class PrintRunable implements Runnable{ static volatile int num =0; public String threadName; public PrintRunable(String threadName){ this.threadName = threadName; } @Override public void run() { synchronized (Thread04.class) { while(num<100){ if(getStr(num).equals(threadName)){ for (int i = 0; i < 1; i++) { System.out.println("线程"+threadName+":"+(++num)); } Thread04.class.notify(); } else{ try { Thread04.class.wait(); } catch (Exception e) { e.printStackTrace(); } } } } } public String getStr(int i){ return i%2==0?"b":"a"; } }
5
/** * 启动2个线程 * 线程1 打印的是1-52之间的数字 * 线程2 打印的是A-Z之间的26个字母 * 结果:输入12a34b56c78d910e...依次类推 * */
package com.thread.base; /** * 启动2个线程 * 线程1 打印的是1-52之间的数字 * 线程2 打印的是A-Z之间的26个字母 * 结果:输入12a34b56c78d910e...依次类推 * */ public class Thread05 { public static void main(String[] args) { Object obj = new Object(); NumThread numThread = new NumThread(obj); CharThread charThread = new CharThread(obj); numThread.start(); charThread.start(); numThread.stop(); } } /** * 打印数字的线程 */ class NumThread extends Thread{ private Object obj; public NumThread(Object obj) { super(); this.obj = obj; } @Override public void run() { synchronized (obj) { for (int i = 1; i <53; i++) { System.out.print(i); if (i%2==0) { //唤醒其它等待的线程 obj.notifyAll(); try { //阻塞当前执行的线程 obj.wait(); } catch (Exception e) { e.printStackTrace(); } } } } } } /** * 打印字符的线程 */ class CharThread extends Thread{ private Object obj; public CharThread(Object obj) { super(); this.obj = obj; } @Override public void run() { synchronized (obj) { for (int i = 0; i <26; i++) { System.out.print((char) ('A' + i)); obj.notifyAll(); try { obj.wait(); } catch (Exception e) { e.printStackTrace(); } } } } }
6
启动多个线程
package com.thread.base; /** * 启动多个线程 * 2个线程做加法 * 2个线程做减法 * 依次输入结果 */ public class Thread06 { public static void main(String[] args) { AddSubThread add = new AddSubThread(); //falg true:add,falg false:sub AddThread add1 = new AddThread(add); AddThread add2 = new AddThread(add); SubTread subTread1 = new SubTread(add); SubTread subTread2 = new SubTread(add); new Thread(add1).start(); new Thread(add2).start(); new Thread(subTread1).start(); new Thread(subTread2).start(); } } /** * 加法线程和减法线程的封装 */ class AddSubThread{ int num=0; boolean falg = false;//阻塞标识 /** * 加法操作 */ public void add (){ synchronized (AddSubThread.class) { while(falg){ try { AddSubThread.class.wait(); } catch (Exception e) { } } System.out.println("add:"+num++); falg = true; AddSubThread.class.notifyAll(); } } /** * 减法操作 */ public void sub(){ synchronized (AddSubThread.class) { while(!falg){ try { AddSubThread.class.wait(); } catch (Exception e) { } } System.out.println("sub:"+num--); falg = false; AddSubThread.class.notifyAll(); } } } /** * 加法线程 */ class AddThread implements Runnable{ private AddSubThread thread; public AddThread(AddSubThread thread) { super(); this.thread = thread; } @Override public void run() { while(true){ thread.add(); } } } /** * 减法线程 */ class SubTread implements Runnable{ private AddSubThread thread; public SubTread(AddSubThread thread) { super(); this.thread = thread; } @Override public void run() { while(true){ thread.sub(); } } }
7 一个线程和其它几个线程共同完成任务
package com.thread.pool; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExecutorsTest { /** * @param args */ public static void main(String[] args) { //线程数 int num = 10; //CountDownLatch是一个同步辅助类也可以使用AtomicInteger替代 CountDownLatch doneSignal = new CountDownLatch(num); ExecutorService pool = Executors.newCachedThreadPool(); for(int i=0;i<num;i++) //在未来某个时间执行给定的命令 pool.execute(new WorkerRunnable(doneSignal, i)); try { doneSignal.await(); } catch (InterruptedException e) { e.printStackTrace(); } //子线程执行完毕,可以开始后续任务处理了 System.out.println("所有任务执行完毕"); } } /** * 子线程 */ class WorkerRunnable implements Runnable { private final CountDownLatch doneSignal; private final int i; WorkerRunnable(CountDownLatch doneSignal, int i) { this.doneSignal = doneSignal; this.i = i; } public void run() { //子线程的任务 try{ doWork(i); }catch (Exception e) { e.printStackTrace(); } //任务执行完毕递减锁存器的计数 doneSignal.countDown(); } void doWork(int i) { System.out.println("这是第"+(i+1)+"个任务"); } }
8 通过多线程之间的协作实现队列机制,通过一个布尔变量
package com.thread.queue; /** * Created by jack on 2018/3/31. * 使用多线程模拟生产者和消费者机制 * 线程a 生产消息 * 线程b 消费消息 * */ public class ThreadQueue01 { public static void main(String[] args) { Resource resource = new Resource(); ProducerThread producerThread = new ProducerThread(resource); ConsumerThread consumerThread = new ConsumerThread(resource); new Thread(producerThread).start(); new Thread(consumerThread).start(); } } /** * 资源管理类 * 包括消息生产和消费 */ class Resource { private int num = 0;//资源序号 private boolean falg = false;//资源标记 /** * 生产消息 */ public synchronized void produce(){ if (falg){ System.out.println("当前消息没有被消费完,清等待消费完再生产.."); try { wait(); } catch (Exception e){ e.printStackTrace(); } } num++; System.out.println(Thread.currentThread().getName() + "生产者------------" + num); falg = true; notifyAll(); } /** * 消费消息 */ public synchronized void consumer (){ if (!falg){ System.out.println("对不起当前没有可消费的消息,清等到消息生产再消费"); try { wait(); } catch (Exception e){ } } System.out.println(Thread.currentThread().getName() + "消费者****" + num); falg = false; notifyAll(); } } /** * 生产线程 */ class ProducerThread implements Runnable{ private Resource resource; public ProducerThread(Resource resource){ this.resource = resource ; } @Override public void run() { while (true){ try { Thread.sleep(1000); } catch (Exception e){ } resource.produce(); } } } /** * 消费线程 */ class ConsumerThread implements Runnable{ private Resource resource; public ConsumerThread(Resource resource){ this.resource = resource ; } @Override public void run() { while (true){ try { Thread.sleep(1000); } catch (Exception e){ } resource.consumer(); } } }
9 通过线程协作实现队列机制
package com.thread.queue; import java.util.ArrayList; import java.util.List; /** * 通过共享list的大小 来决定是否阻塞对应线程 */ public class ThreadQueue02 implements Runnable { private String name; private List<String> list = new ArrayList<String>(); private final int size = 10; /** * 模拟消息的生产 * @param num * @throws Exception */ public void produce(int num) throws Exception { while (true) { synchronized (list) { while (list.size() + num > size) { System.out.println(Thread.currentThread().getName()+"生产过剩,等待消费"); list.wait(); } System.out.println(Thread.currentThread().getName()+"正在生产"); for (int i = 0; i < num; i++) { list.add("hello, world"); } list.notify(); } Thread.sleep(1000); } } /** * 模拟消息的消费 * @throws Exception */ public void consume() throws Exception { while (true) { synchronized (list) { while (list.size() == 0) { System.out.println(Thread.currentThread().getName()+"已无产品可消费,等待生产"); list.wait(); } System.out.println(Thread.currentThread().getName()+"正在消费"); list.remove(0); list.notify(); } Thread.sleep(1000); } } public void setName(String name) { this.name = name; } public void run() { try { if ("producer".equals(name)) { produce(1); } else { consume(); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { try { ThreadQueue02 myThread = new ThreadQueue02(); myThread.setName("producer"); Thread t1 = new Thread(myThread); Thread t4 = new Thread(myThread); t1.start(); t4.start(); Thread.sleep(1); myThread.setName("consumer"); Thread t2 = new Thread(myThread); Thread t3 = new Thread(myThread); t2.start(); t3.start(); } catch (Exception e) { } } }
10
直接使用阻塞队列来模拟生产者和消费者
package com.thread.queue; import java.util.Random; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; /** * Created by jack on 2018/3/31. * 直接使用阻塞队列来模拟生产者和消费者 */ @SuppressWarnings("all") public class ThreadQueue03 { public static void main(String[] args)throws Exception { // 声明一个容量为10的缓存队列 BlockingQueue<String> queue = new LinkedBlockingQueue<String>(10); ProducerRunnable producer1 = new ProducerRunnable(queue); ProducerRunnable producer2 = new ProducerRunnable(queue); ProducerRunnable producer3 = new ProducerRunnable(queue); ConsumerRunnable consumer = new ConsumerRunnable(queue); // 借助Executors ExecutorService service = Executors.newCachedThreadPool(); // 启动线程 service.execute(producer1); service.execute(producer2); service.execute(producer3); service.execute(consumer); // 执行10s Thread.sleep(10 * 1000); producer1.stop(); producer2.stop(); producer3.stop(); Thread.sleep(2000); // 退出Executor service.shutdown(); } } /** * 生产线程 */ class ProducerRunnable implements Runnable{ private static final int DEFAULT_RANGE_FOR_SLEEP = 1000; private BlockingQueue blockingQueue; private volatile boolean isRunning = true; private static AtomicInteger count = new AtomicInteger(); public ProducerRunnable(BlockingQueue blockingQueue){ this.blockingQueue = blockingQueue; } @Override public void run() { String data = null; Random r = new Random(); System.out.println("启动生产者线程"); try { while (isRunning){ System.out.println("正在生产数据"); Thread.sleep(r.nextInt(DEFAULT_RANGE_FOR_SLEEP)); data = "data:" + count.incrementAndGet(); System.out.println("将数据:" + data + "放入队列..."); if (!blockingQueue.offer(data, 2, TimeUnit.SECONDS)) { System.out.println("放入数据失败:" + data); } } } catch (Exception e){ Thread.currentThread().interrupt(); } finally { System.out.println("退出生产者线程!"); } } public void stop() { isRunning = false; } } /** * 消费线程 */ class ConsumerRunnable implements Runnable{ private static final int DEFAULT_RANGE_FOR_SLEEP = 1000; private BlockingQueue blockingQueue; volatile boolean isRunning = true; public ConsumerRunnable(BlockingQueue blockingQueue){ this.blockingQueue = blockingQueue; } @Override public void run() { System.out.println("启动消费者线程!"); Random r = new Random(); try { while (isRunning) { System.out.println("正从队列获取数据..."); String data = blockingQueue.poll(2, TimeUnit.SECONDS).toString(); if (null != data) { System.out.println("拿到数据:" + data); System.out.println("正在消费数据:" + data); Thread.sleep(r.nextInt(DEFAULT_RANGE_FOR_SLEEP)); } else { // 超过2s还没数据,认为所有生产线程都已经退出,自动退出消费线程。 isRunning = false; } } } catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); } finally { System.out.println("退出消费者线程!"); } } }