1. ThreadLocal使用
public class Main {
/**
* 每一个线程有个 一个ThreadLocal
* 为单独线程 共享数据
*/
public static void main(String[] args) {
ThreadLocal<String> tl=new ThreadLocal<>();
tl.set("xiaoming"); // 保存数据
System.out.println(tl.get()); // 获取保存的数据
// 线程结束,必须释放,否则内存泄露
// 什么叫做内存泄露:一块内存在堆中,没有栈变量指向的时候, 这个就是内存泄露
// 什么叫内存溢出: 栈内存满了
tl.remove();
tl=null;
}
}
2. JUC
jdk1.5 以后 Java 提供了JUC 处理多线程
线程安全容器
Vector,Hashtable 线程安全容器,使用syschronized实现
java.util.concurrent.* 下 ConcurrentHashMap 也实现线程安全的,使用Java8 CAS实现【底层C】
都是 哈希表 :功能对比
java.util.concurrent.* 包下类 在高并发 效率高比 java.utils.hashmap 【简称 juc】
public class Main {
/**
* 每一个线程有个 一个ThreadLocal
* 为单独线程 共享数据
*/
public static void main(String[] args) {
/**
* jdk1.5 以后 Java 提供了JUC 处理多线程
* 线程安全容器
* Vector,Hashtable 线程安全容器,使用syschronized实现
* java.util.concurrent.* 下 ConcurrentHashMap 也实现线程安全的,使用Java8 CAS实现【底层C】
* 都是 哈希表 :功能对比
* java.util.concurrent.* 包下类 在高并发 效率高比 java.utils.hashmap 【简称 juc】
*/
ConcurrentHashMap<String, String> con=new ConcurrentHashMap<>();
con.put("name", "小明");
System.out.println(con.get("name"));
}
}
3. 任务接口
Callable : 返回值 Runnable : 没有返回值
任务接口使用:
package com.denganzhi.pp;
import java.awt.SystemColor;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main2 {
public static void main(String[] args) {
// 任务接口
// Callable : 返回值
// Runnable : 没有返回值
//创建线程,这里必须要指定线程的个数
// ExecutorService 可以理解为 引擎, 任务调用者
ExecutorService or=Executors.newFixedThreadPool(1);
//执行线程获取返回值 submit 又返回值
Future<String> f=or.submit(new Callable<String>() {
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
Thread.sleep(5000);
return "返回值";
}
});
try {
System.out.println("线程是否结束:"+f.isDone());
// 这里会阻塞
String str=f.get();
System.out.println(str);
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 关闭 资源, 优雅关闭,把任务完成才关闭 , 不是立即关闭
or.shutdown();
System.out.println(or.isTerminated()); // 是否已经关闭,回收资源
}
}
4. 线程池 Api
逻辑核心: 一块CPU可以运行几个线程 8核
4.1.newFixedThreadPool
// 当任务数量大于 线程池容量时候,线程池没有足够的Runnable去执行 任务数, 当线程有空闲的时候,自动从队列中取出任务
// 使用场景:实际开发中,系统支持线程 上限,不能够随意 无限提供线程池
// 固定容量线程池 相当于数组
// 如何根据 cpu 核数 计算 创建线程数量
public static void main(String[] args) {
/**
* Executors: 线程池 父类接口
* Jvm关闭,线程池生命周期结束
* 手动调用shutdown, 线程任务执行完毕以后,自动关闭线程池,如果不关闭,那么一直在
*/
// 当任务数量大于 线程池容量时候,线程池没有足够的Runnable去执行 任务数, 当线程有空闲的时候,自动从队列中取出任务
// 使用场景:实际开发中,系统支持线程 上限,不能够随意 无限提供线程池
// 固定容量线程池 相当于数组
// 如何根据 cpu 核数 计算 创建线程数量
ExecutorService service= Executors.newFixedThreadPool(5);
for (int i = 0; i <10; i++) {
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(" thread_name:"+ Thread.currentThread().getName());
}
});
}
service.shutdown();
}
4.2. newCachedThreadPool
* 添加 任务,那么创建 新线程 , 自动扩容
* 创建的 线程 默认 空闲时间 60S,没有处理任务 ,那么自动销毁
* 容量最大(Integer.MAX_VALUE)
* 应用:用于测试 ,无限 任务
public static void main(String[] args) {
/***
* 添加 任务,那么创建 新线程 , 自动扩容
* 创建的 线程 默认 空闲时间 60S,没有处理任务 ,那么自动销毁
* 容量最大(Integer.MAX_VALUE)
* 应用:用于测试 ,无限 任务
*/
ExecutorService cachedPool= Executors.newCachedThreadPool();
for (int i = 0; i <5 ; i++) {
cachedPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(" thread_name:"+ Thread.currentThread().getName());
}
});
}
cachedPool.shutdown();
}
4.3. newScheduledThreadPool
* 应用 : 用于定时执行 任务
public static void main(String[] args) {
/***
* 任务线程,没有用,没有试出来
* 应用 : 用于定时执行 任务
*/
ScheduledExecutorService service=Executors.newScheduledThreadPool(3);
// 第一次任务执行间隔,多次任务执行间隔时间
System.out.println("start:"+new Date());
// 3个线程执行3个任务,4秒以后执行第二批
for (int i = 0; i <3 ; i++) {
service.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.err.println(new Date());
System.err.println(Thread.currentThread().getId());
}
}, 3, 4, TimeUnit.SECONDS);
}
service.shutdown();
}
4.4. newSingleThreadExecutor
// 单一 线程 容器, 只有一个 线程
public static void main(String[] args) {
// 单一 线程 容器, 只有一个 线程
ExecutorService service1= Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
service1.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程数量唯一"+ Thread.currentThread().getId());
}
});
}
service1.shutdown();
}