线程状态
线程池ThreadPool
理解:吃饭碗,用完就摔太浪费,线程池解决。
如何使用线程池?
1.默认线程池Executors
创建单线程池 newSingleThreadExecutor
package com.lu.day13;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 创建单线程池:池中最多只有一个线程,创建线程之后,池中有0个线程,来了任务之后才会创建线程,不销毁线程,复用线程
*/
public class SingleThreadDemo {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(() -> System.out.println("执行了1"));
executorService.execute(() -> System.out.println("执行了2"));
executorService.execute(() -> System.out.println("执行了3"));
}
}
创建缓存线程池(最大能创建int的最大值)newCachedThreadPool
package com.lu.day13;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 创建缓存线程池:最多能创建Integer.MAX_VALUE个线程(不允许使用)
*/
public class CachedThreadDemo {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(()->{
System.out.println(123);
});
//优雅终止
executorService.shutdown();
//立即终止
executorService.shutdownNow();
}
}
创建固定数量的线程池 newFixedThreadPool
package com.lu.day13;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 创建固定数量的线程池:最大值Integer.MAX_VALUE
*/
public class FixedThreadDemo {
public static void main(String[] args) {//没执行任务就没有创建线程
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(() -> System.out.println("线程池创建成功1"));
executorService.execute(() -> System.out.println("线程池创建成功2"));
executorService.execute(() -> System.out.println("线程池创建成功3"));
}
}
定时任务线程池newScheduledThreadPool
package com.lu.day13;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
* 定时任务线程池
* 定时任务:以固定的频率周期性的执行任务
*/
public class ScheduledThreadDemo {
public static void main(String[] args) {
//定时任务线程池服务对象
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService
.scheduleAtFixedRate(() -> System.out.println("定时任务线程池"), 0, 1, java.util.concurrent.TimeUnit.SECONDS);
//不用关闭
}
}
提交任务(调用submit方法)
关闭线程池(调用shutDown方法)
2.Executors的弊端
oom栈内存溢出异常
3.手动指定参数线程池ThreadPoolExecutor(超级重点)
package com.lu.day13;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ManualThreadPool {
public static void main(String[] args) {
/*
核心线程数:任务提交到线程池之后,创建之后不会销毁
最大线程数:用来计算非核心,非核心线程数会被销毁
非核心线程空闲活跃时间:指定非核心在不处理任务时的销毁时间
空闲时间单位:指定非核心销毁的时间单位
线程工厂:可以指定线程的创建方式(指定线程名字)
任务队列:任务堆积多少
拒绝策略:任务队列满了,触发拒绝策略(有四种)
*/
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,10,5,
TimeUnit.MINUTES,new ArrayBlockingQueue<>(100),new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 300; i++) {
threadPoolExecutor.execute(() -> System.out.println(Thread.currentThread().getName()));
}
}
}
4.拒绝策略详解
补充
package com.lu.day13;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 基本数据类型:四类八种
* 包装类:八种(浮点数无法精确计算,超过long,double的数无法存存储)
* 大类:以Big开头的类BigDecimal、BigInteger
* 以上都还有一个统一的缺点:多线程下无法保证原子性
* 原子类:以Atomic开头的类,保证基本数据类型的原子操作的原子类
*/
public class Test {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(1);
System.out.println(atomicInteger.incrementAndGet());//a++
System.out.println(atomicInteger.decrementAndGet());//a--
}
}
网络编程
1.ip
package com.lu.day13.Internet;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Test {
public static void main(String[] args) {
try {
InetAddress byName = InetAddress.getByName("192.168.32.243");
//获取主机名称
System.out.println(byName.getHostName());
//获取主机地址
System.out.println(byName.getHostAddress());
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
}
2.端口
3.协议
java使用DUP通信
package com.lu.day13.Internet;
import java.io.IOException;
import java.net.*;
/**
* 客户端
*/
public class Client {
public static void main(String[] args) throws IOException {
//1.创建代表UDP协议的传输对象
DatagramSocket datagramSocket = new DatagramSocket();
String mes = """
${AnsiColor.BRIGHT_YELLOW}
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\\ = /O
____/`---'\\____
.' \\\\| |// `.
/ \\\\||| : |||// \\
/ _||||| -:- |||||- \\
| | \\\\\\ - /// | |
| \\_| ''\\---/'' | |
\\ .-\\__ `-` ___/-. /
___`. .' /--.--\\ `. . __
."" '< `.___\\_<|>_/___.' >'"".
| | : `- \\`.;`\\ _ /`;.`/ - ` : | |
\\ \\ `-. \\_ __\\ /__ _/ .-` / /
======`-.____`-.___\\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 佛祖保佑 永不宕机 永无BUG //
""";
//2.创建传输(携带)数据的数据包对象
DatagramPacket datagramPacket = new DatagramPacket(mes.getBytes(), 0, mes.getBytes().length,InetAddress.getByName("192.168.32.224"),9999);
datagramSocket.send(datagramPacket);
}
}
package com.lu.day13.Internet;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class Server {
public static void main(String[] args) {
try (DatagramSocket datagramSocket = new DatagramSocket(9999)) {
while (true) {
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length);
System.out.println("等待接收消息: ");
datagramSocket.receive(datagramPacket);
System.out.println(new String(bytes, 0, datagramPacket.getLength()));
}
} catch (SocketException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}