记录了一些Java多线程demo
多线程
Thread
通过继承Thread类重写run函数来建立多线程,优点是操作简单,缺点是无法继承其他类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class ThreadDemo1 { public static void main(String[] args) { Thread t = new MyThread(); t.start();
for (int i = 0; i < 5; i++) { System.out.println("主线程: " + i); } } }
class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println("子线程: " + i); } } }
|
Runnable
通过实现Runnable接口实现多线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class ThreadDemo2 { public static void main(String[] args) { Runnable r = new MyRunnable(); Thread t = new Thread(r); t.start();
for (int i = 0; i < 10; i++) { System.out.println("主线程:" + i); } } }
class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("子线程:" + i); } } }
|
Callable
通过实现Callable接口实现多线程,优点是能获取线程返回的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package 多线程;
import java.util.concurrent.Callable; import java.util.concurrent.FutureTask;
public class ThreadDemo3 { public static void main(String[] args) { Callable<String> c = new MyCallable(); FutureTask<String> f = new FutureTask<>(c); Thread t = new Thread(f); t.start();
try{ System.out.println(f.get()); }catch (Exception e){ e.printStackTrace(); } } }
class MyCallable implements Callable<String> { @Override public String call() throws Exception { return "这是子线程"; } }
|
public void run() |
子线程运行代码 |
public void start() |
启动子线程 |
public String getName() |
获取子线程名称 |
public void setName(String name) |
设置子线程名称 |
public static Thread currentThread() |
获取当前执行的线程对象 |
public static Thread sleep(int time) |
子线程休眠 |
public final void join() |
将子线程插入当前主线程之前执行 |
线程同步
由于子线程执行是无序,当两个子线程同时执行时有可能出现线程安全问题。比如两个人同时抢同一张车票,前一个人将车票买走还没更新时被另一个人再买一次,那么同一个车票就就会被两个人同时购买。线程同步则是解决线程安全问题的方案。
同步代码块
通过将核心代码上锁实现同步,同一时间只有一个线程可以执行代码块里的内容,其他线程将会堵塞等待。
1 2 3
| synchronized (sdx){ 核心代码 }
|
同步方法
1 2 3
| public synchronized void drawMoney(){ ... ... }
|
lock锁
1 2 3
| Lock lk = new ReentrantLock(); lk.look; lk.unlook;
|
线程通讯
void wait() |
让当前线程等待并释放锁 |
void notify() |
唤醒一个等待的线程 |
void notifyAll() |
唤醒所有等待的线程 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| public class ConsumerThread extends Thread{ private Desk desk; public ConsumerThread(Desk desk, String name){ super(name); this.desk = desk; } @Override public void run() { while(true){ try { Thread.sleep(1000); this.desk.get(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }
public class MakeThread extends Thread{ private Desk desk; public MakeThread(Desk desk,String name){ super(name); this.desk = desk; } @Override public void run() { while (true){ try { Thread.sleep(1000); this.desk.put(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }
public class Desk { private String data;
public synchronized void get() throws InterruptedException { String name = Thread.currentThread().getName(); if (data == null){ this.notifyAll(); this.wait(); } else { System.out.println(name + "吃了" + data); data = null; this.notifyAll(); this.wait(); } }
public synchronized void put() throws InterruptedException { String name = Thread.currentThread().getName(); if (data == null){ data = name + "制作的包子"; System.out.println(name + "制作了一个包子"); this.notifyAll(); this.wait(); }else { this.notifyAll(); this.wait(); } } }
public class Test { public static void main(String[] args) { Desk desk = new Desk(); new MakeThread(desk, "康师傅").start(); new MakeThread(desk, "吴师傅").start(); new MakeThread(desk, "谢师傅").start();
new ConsumerThread(desk, "付先生").start(); new ConsumerThread(desk, "赵先生").start(); } }
|
线程池
由于创建新线程开销比较大,线程过多会影响性能,线程池为解决该问题而存在
corePoolSize |
指定线程池核心线程的数量 |
maximumPoolSize |
指定线程池的最大线程数量 |
keepAliveTime |
指定临时线程的存活时间 |
unit |
指定临时线程存活的时间单位 |
workQueue |
指定线程池的任务对列 |
threadFactory |
指定线程池的线程工厂 |
handler |
指定线程池的任务拒绝策略 |
ThreadPoolExcutor.AbortPolicy |
丢弃任务并抛出RejectedExecutionException异常 |
ThreadPoolExcutor.DiscardPolicy |
丢弃任务,但不抛出异常 |
ThreadPoolExcutor.Discardldestiscardldestolicy |
抛弃任务中等待最久的任务,然后把当前任务加入队列 |
ThreadPoolExcutor.CallerRunsPolicy |
由主线程负责调用任务的run()方法从而绕过线程池直接执行 |
执行Runnable任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import java.util.concurrent.*;
public class ThreadPoolExecutorDemo1 { public static void main(String[] args) { ExecutorService pool = new ThreadPoolExecutor(3, 5, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); pool.execute(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "执行任务" + i); } } }); pool.execute(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "执行任务" + i); } } }); pool.execute(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "执行任务" + i); } } }); } }
|
执行Callable任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import java.util.concurrent.*;
public class ThreadPoolExecutorDemo2 { public static void main(String[] args) { ExecutorService pool = new ThreadPoolExecutor(3, 5, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); Future<String> f1 = pool.submit(new Callable<String>() { @Override public String call() throws Exception { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "执行任务" + i); } return "Thread.currentThread().getName()"; } }); Future<String> f2 = pool.submit(new Callable<String>() { @Override public String call() throws Exception { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "执行任务" + i); } return "Thread.currentThread().getName()"; } }); Future<String> f3 = pool.submit(new Callable<String>() { @Override public String call() throws Exception { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "执行任务" + i); } return Thread.currentThread().getName().toString(); } }); try { System.out.println(f1.get()); System.out.println(f2.get()); System.out.println(f3.get()); } catch (Exception e) { e.printStackTrace(); } } }
|
工具类Executors创建线程池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import java.util.concurrent.*;
public class ExecytorsDemo { public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(3); pool.execute(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "执行任务" + i); } } }); pool.execute(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "执行任务" + i); } } }); pool.execute(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "执行任务" + i); } } }); } }
|
public static ExecutorService newFixedThreadPool(int number) |
创建固定线程数量的进程池,如果某进程执行异常结束则会补充一个新进程 |
public static ExecutorService newSingleThreadExecutor() |
创建一个只有一个线程的进程池,如果该进程执行异常结束则会补充一个新进程 |
public static ExecutorService newCachedThreadPool |
线程数量随着任务增加而增加,如果线程任务执行完毕且空闲60s则会被回收掉 |
public static ExecutorService newScheduledThreadPool(int
corePoolSize) |
创建一个进程池,可以实现在给定延迟后运行任务或者定期执行任务 |
!!! 使用Executors可能会出现系统风险!!!