本文最后更新于:2025年2月18日 下午
Java多线程
多线程实现方式
一:继承Thread
类
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
| package Example1;
public class Demo {
public static void main(String[] args) { Test test = new Test(); Test test1 = new Test(); test.setName("窗口1:"); test1.setName("窗口2:"); test.start(); test1.start(); } }
class Test extends Thread {
public static int ticket = 10;
@Override public void run() { while (true){ synchronized (SellPort1.class){ if (ticket == 0){ break; }else { ticket--; System.out.println(Thread.currentThread().getName()+"卖出一张票!剩余票数"+ticket); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } } }
|
二:实现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 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| package Example1;
public class Demo {
public static void main(String[] args) { Test test = new Test(); Thread t1 = new Thread(test); Thread t2 = new Thread(test); t1.setName("窗口1:"); t2.setName("窗口2:"); t1.start(); t2.start(); } }
class Test implements Runnable {
public static int ticket = 10;
@Override public void run() { while (true){ synchronized (SellPort1.class){ if (ticket == 0){ break; }else { ticket--; System.out.println(Thread.currentThread().getName()+"卖出一张票!剩余票数"+ticket); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } } }
|
三:实现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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| package Example1;
import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.Callable;
public class Demo {
public static void main(String[] args) throws ExecutionException, InterruptedException { Test t = new Test(); FutureTask<Integer> futureTask = new FutureTask<>(t,); FutureTask<Integer> futureTask2 = new FutureTask<>(t); Thread t1 = new Thread(futureTask,"线程1"); Thread t2 = new Thread(futureTask2,"线程2"); t1.start(); t2.start(); Integer o = futureTask.get(); Integer o2 = futureTask.get(); System.out.println(o); System.out.println(o2); } }
class Test implements Callable<Integer> {
public static int ticket = 10;
@Override public Integer run() { while (true){ synchronized (Test.class){ if (ticket == 0){ break; }else { ticket--; System.out.println(Thread.currentThread().getName()+"卖出一张票!剩余票数"+ticket); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } if(Thread.currentThread().getName() == "线程1"){ return 1; }else{ return 2; } } }
|
成员方法
方法名称 |
说明 |
public final String getName() |
返回此线程的名称 |
public final synchronized void setName(String name) |
设置线程名称 |
public static native Thread currentThread(); |
获取当前线程对象 |
public static native void sleep(long millis) |
让线程休眠指定时间 |
public final void setPriority(int newPriority) |
设置线程优先级(默认5,数值越大越优先) |
public final int getPriority() |
获取线程优先级(默认5,数值越大越优先) |
public final void setDaemon(boolean on) |
设置线程守护 |
public static native void yield(); |
出让线程 |
public final void join() |
插入线程 |
线程生命周期
创建 -> 就绪 -> 运行 -> (阻塞 -> 等待) -> 结束
同步关键字 synchronized
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
| synchronized 可修饰方法 -> 同步方法 public final synchronized void setName(String name){}
synchronized (Test.class){ if (ticket == 0){ break; }else { ticket--; System.out.println(Thread.currentThread().getName()+"卖出一张票!剩余票数"+ticket); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
1、循环 2、同步代码块 3、判断共享数据是否到末尾,如果到了末尾就break或者怎么怎么样 4、判断共享数据是否到末尾,如果没到末尾怎么怎么样
|
Lock
锁,手动加解锁
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
| package ThreadLock;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;
public class MyThread extends Thread {
static int counter = 0; static Lock lock = new ReentrantLock();
@Override public void run() { while (true){ lock.lock();
if (counter == 100){
break; }else { counter++; System.out.println(Thread.currentThread().getName()+"正在售卖第"+counter+"张票!!!"); } lock.unlock(); } lock.unlock(); } }
|
需要避免的情况 --> 【死锁】
死锁通常是因为嵌套锁产生的,尽量避免嵌套。
等待唤醒【生产者和消费者】
方法名称 |
说明 |
public final void wait() |
线程等待,直到被其他线程唤醒 |
public final native void notify(); |
随机唤醒单个线程 |
public final native void notifyAll(); |
唤醒(同一 JVM 中或同一个对象上)等待的所有线程 |
启动类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package wait;
public class MyThread{
public static void main(String[] args) { Cook cook = new Cook(); Eat eat = new Eat(); cook.setName("厨师"); eat.setName("顾客"); cook.start(); eat.start(); } }
|
桌面类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package wait;
public class Desk {
public static int foodStatus = 0;
public static int count = 10;
public static Object lock = new Object(); }
|
厨师类(生产者)
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
| package wait;
public class Cook extends Thread {
@Override public void run() { while (true){ synchronized (Desk.lock) { if (Desk.count == 0){ break; }else { if (Desk.foodStatus == 1){ try { Desk.lock.wait(); }catch (Exception e){ e.printStackTrace(); } }else { System.out.println("厨师做了一碗面条。"); Desk.foodStatus = 1; Desk.lock.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
| package wait;
public class Eat extends Thread{
@Override public void run() { while (true){ synchronized (Desk.lock) { if (Desk.count == 0){ break; }else {
if (Desk.foodStatus == 0) { try { Desk.lock.wait(); } catch (Exception e) { e.printStackTrace(); } } else { Desk.count--; System.out.println("顾客吃了一碗面条。还能再吃"+Desk.count+"碗"); Desk.foodStatus = 0; Desk.lock.notify();
} } } } } }
|
阻塞队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package Block;
import java.util.concurrent.ArrayBlockingQueue;
public class Demo {
public static void main(String[] args) { ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1); Cook cook = new Cook(queue); Eat eat = new Eat(queue);
cook.start(); eat.start(); } }
|
生产者
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
| package Block;
import java.util.concurrent.ArrayBlockingQueue;
public class Cook extends Thread{
ArrayBlockingQueue<String> queue;
public Cook(ArrayBlockingQueue<String> queue) { this.queue = queue; }
@Override public void run() { while (true){ try{ queue.put("面条"); System.out.println("厨师做了一碗面条"); }catch (Exception e){ e.printStackTrace(); } } } }
|
消费者
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
| package Block;
import java.util.concurrent.ArrayBlockingQueue;
public class Eat extends Thread{
ArrayBlockingQueue<String> queue;
public Eat(ArrayBlockingQueue<String> queue) { this.queue = queue; }
@Override public void run() {
while (true){ try{ String food = queue.take(); System.out.println("顾客吃了一碗"+food); System.out.println("剩余"+queue.size()); }catch (Exception e){ e.printStackTrace(); } } } }
|
线程池
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
| package MyThreadPool;
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
public class Demo { public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.submit(new MyThread()); Thread.sleep(1000); threadPool.submit(new MyThread()); Thread.sleep(1000); threadPool.submit(new MyThread()); Thread.sleep(1000); threadPool.submit(new MyThread()); Thread.sleep(1000); threadPool.submit(new MyThread());
threadPool.shutdown(); } }
class MyThread implements Runnable {
static int count = 0;
@Override public void run() { System.out.println(Thread.currentThread().getName()+":"+count); } }
|
自定义线程池
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
| package MyThreadPool;
import java.util.concurrent.*;
public class MyPool {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 3, 6, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy() ); } }
|
1 2 3 4 5 6 7 8 9 10
| package MyThreadPool;
public class Processor { public static void main(String[] args) { System.out.println(Runtime.getRuntime().availableProcessors()); } }
|
线程池计算
CPU密集型计算 – > 最大并行数 + 1
I/O密集型计算 --> 最大并行数* 期望CPU利用率*【(CPU计算时间+CPU等待时间)/CPU计算时间】
补充