多线程
多个线程同时或交替运行, 单核CPU为顺序执行(交替执行), 多核情况下, 每个CPU有自己的运算器, 所以在多个CPU中可以同时运行.
创建线程的方式
1.继承Thread
1 2 3 4 5 6 7 8
| public class MyThread extends Thread {
@Override public void run() { super.run(); System.out.println(Thread.currentThread().getName() + "执行完毕"); } }
|
1 2 3 4 5 6 7 8 9 10 11
| public class ThreadTest {
public static void main(String[] args) {
MyThread myThread = new MyThread(); myThread.setName("测试"); myThread.start(); System.out.println(Thread.currentThread().getName() + "执行完毕"); } }
|
开始线程, 可以看出main线程和测试线程是两个独立的线程
调用myThread.run();方法相当于直接在主线程运行run方法, 而不是开启一个新的线程去执行
2.实现Runnable接口
1 2 3 4 5 6 7
| public class MyRunable implements Runnable {
@Override public void run() { System.out.println(Thread.currentThread().getName() + "执行完毕"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class ThreadTest {
public static void main(String[] args) {
MyRunable runable = new MyRunable();
Thread thread = new Thread(runable); thread.start();
System.out.println(Thread.currentThread().getName() + "执行完毕"); } }
|
3.使用线程池
3.1 可以在spring中配置相关线程池, 使用时从容器取出即可, 也可以自己声明线程池
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
| <bean id="threadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5"/> <property name="maxPoolSize" value="20"/>
<property name="keepAliveSeconds" value="300"/>
<property name="queueCapacity" value="2000"/>
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"/> </property>
</bean>
|
3.2 Executors 创建线程池
1 2 3 4 5 6 7 8 9 10 11 12
| public class ThreadTest {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) { threadPool.execute(new MyRunable()); }
} }
|
当手动创建线程池时, 如果IDEA安装阿里 P3C 插件后会报错提示以下内容, 建议
1 2 3 4 5 6
| 线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明: Executors 返回的线程池对象的弊端如下: 1) FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。 2) CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE, 可能会创建大量的线程,从而导致 OOM。
|
建议使用如下方式:
1 2 3 4 5 6 7 8 9 10
| public class ThreadTest {
public static void main(String[] args) { ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(3, new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").build()); executorService.scheduleAtFixedRate(new MyRunable(), 0, 1, TimeUnit.SECONDS);
} }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class ThreadTest {
public static void main(String[] args) {
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() .setNameFormat("demo-pool-%d").build();
ExecutorService pool = new ThreadPoolExecutor(5, 20, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
pool.execute(()-> System.out.println(Thread.currentThread().getName())); pool.shutdown();
} }
|
线程优先级
1.myThread.setPriority(1);设置优先级
2.优先级从低到高为 1-10, Thread类提供 Thread.MIN_PRIORITY=1, Thread.NORM_PRIORITY=5, Thread.MAX_PRIORITY=10
3.默认优先级为 5 即 NORM_PRIORITY
4.优先级高的仅代表获取进入运行机会的几率大, 并不代表一定会比优先级低的先执行
sleep()和wait()
1.sleep()线程未释放锁, 时间结束后线程继续执行
2.wait线程释放锁, 需要使用notify或notifyAll
3.wait常用于线程之间的交互
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| package com.liuzhihang.tool.alternate;
public class AlternateNum {
public static void main(String[] args) {
Num num = new Num();
Thread thread1 = new Thread(new Odd(num)); Thread thread2 = new Thread(new Even(num));
thread1.start(); thread2.start();
} }
class Num { int anInt = 1; boolean flag = true;
}
class Odd implements Runnable {
private Num num;
public Odd(Num num) { this.num = num; }
@Override public void run() { while (num.anInt < 1000) { synchronized (num) { if (num.flag) { System.out.println("奇数 -> " + num.anInt); num.anInt++; num.flag = false; num.notify();
} else { try { num.wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
} }
} }
class Even implements Runnable {
private Num num;
public Even(Num num) { this.num = num; }
@Override public void run() { while (num.anInt < 1000) { synchronized (num) { if (!num.flag) { System.out.println("偶数 -> " + num.anInt); num.anInt++; num.flag = true; num.notify();
} else { try { num.wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
} }
} }
|