最简单开启多线程
//三个线程 业务写在 里面 分批次执行
new Thread(()->{
testLock.buy();
}).start();
new Thread(()->{
testLock.buy();
}).start();
new Thread(()->{
testLock.buy();
}).start();
基础详解
多线程以及代理模式
package com.ruoyi.job.dmeo;
//静态代理总结
//真实对象和代理对象都要实现同一个接口
//代理对象要 代理真实角色
//都去实现 结婚的接口类 都是结婚的子类, (方法定义传乐器, 现实传 唢呐、吉他、钢琴)
// 多线程也是代理模式, 实现接口 再去拓展
//好处;
//代理对象可以做很多真实对象做不了的事情 真交对象专注傲自已的事情
public class DaiLiDemo {
public static void main(String[] args) {
// Thread implements Runnable ,runnable只做run方法,Thread就是他的代理
new Thread(()-> System.out.println("多线程代理")).start();
new WinddingCompany(new You()).happyMarry();
}
}
//结婚的接口类
interface Marry{
void happyMarry();
}
//真实角色 你
class You implements Marry{
@Override
public void happyMarry() {
System.out.println("我要结婚了,敲开心!");
}
}
// 代理角色 婚庆公司
class WinddingCompany implements Marry{
private Marry marry;
public WinddingCompany(Marry marry) {
this.marry = marry;
}
@Override
public void happyMarry() {
before();
this.marry.happyMarry();
after();
}
private void after() {
System.out.println("结婚后收拾现场!");
}
private void before() {
System.out.println("结婚前收彩礼!");
}
}
线程优先级
优先级低只是意味着获得调度的概率低.并不是优先级低就不会被调用了.这都是看CPU的调度
使用多线程 先设置优先级, 1-10 , 10最优先 1最慢, 1-10以外的数字报错, 默认是5公平竞争
thread1.setPriority(10); //设置优先级
public class ThreadPriorityDemo {
public static void main(String[] args) {
Thread thread1=new Thread(()-> System.out.println("-->"+Thread.currentThread().getPriority()));
Thread thread2=new Thread(()-> System.out.println("-->"+Thread.currentThread().getPriority()));
Thread thread3=new Thread(()-> System.out.println("-->"+Thread.currentThread().getPriority()));
Thread thread4=new Thread(()-> System.out.println("-->"+Thread.currentThread().getPriority()));
Thread thread5=new Thread(()-> System.out.println("-->"+Thread.currentThread().getPriority()));
thread1.setPriority(1);
thread2.setPriority(9);
thread3.setPriority(7);
thread4.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
}
}
线程停止
// 不建议使用官方stop 自己定义一个标识符 true 和false 去停止
public class ThreadStopDemo implements Runnable {
//设置一个标识
private boolean biaoshi;
@Override
public void run() {
int i=0;
System.out.println("县城"+i++);
}
public void stop(){
this.biaoshi=false;
}
public static void main(String[] args) {
ThreadStopDemo threadStopDemo=new ThreadStopDemo();
new Thread(threadStopDemo).start();
for (int i = 0; i < 10000; i++) {
System.out.println("main"+i);
if(i==9000){
threadStopDemo.stop();
System.out.println("县城该停止了");
}
}
}
}
线程睡眠 sleep
睡眠不会释放锁
Thread.sleep(2000)//2000ms 2s
线程礼让 yield
礼让不一定成功,看cpu心情
Thread.yield();
线程插队 join
线程状态
守护线程
线程分为用户线程和守护线程,虚拟机必须确保用户线程执行完毕,虚拟机不用等待守护线程执行完毕, 例如,后台记录操作日志,监控内存,垃圾回收等待…
//设置守护线程
public class ThreadDaemonDemo {
public static void main(String[] args) {
Thread thread=new Thread(new God());
thread.setDaemon(true);//设置为守护线程 直到所有线程执行完毕 ,还会执行一会儿然后结束
thread.start();
new Thread(new Yous()).start();
}
}
//上帝
class God implements Runnable{
@Override
public void run() {
while(true){
System.out.println("上帝守护者你");
}
}
}
//你
class Yous implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("好好活好每一天");
}
System.out.println("=======God By=======");
}
}
并发
线程不安全例子
//线程不安全 集合
public class ThreadNoSafe {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
for (int i = 0; i < 100000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
//3个人 抢票 出现同时抢到票的情况
public class ThreadBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket=new BuyTicket();
Thread thread1=new Thread(buyTicket,"小明");
Thread thread2=new Thread(buyTicket,"小红");
Thread thread3=new Thread(buyTicket,"黄牛");
thread1.start();
thread2.start();
thread3.start();
}
}
class BuyTicket implements Runnable{
private int ticket=10;
private boolean flag=true;
@Override
public void run() {
while(flag){
buy();
}
}
public void buy(){
while(ticket<=0){
flag=false;
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"拿到了"+ticket--);
}
}
synchronized (同步)
实现就是 队列和锁: 10个人排队上厕所, 一个人进去锁门,出来后另一人进去锁门。
加锁影响性能,一般需要增删改的方法加锁, 查询不需要锁
- synchronized 方法 (锁的是this 当前类)
- synchronized 代码块 (可以锁 需要增删改的类)
锁 方法
方法上加 synchronized 其实锁的是this 当前类的增删改
如果 HeaderService 方法 调用了 Item类增删改 就只能锁块,锁方法失效
//3个人 抢票 出现同时抢到票的情况
public class ThreadBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket=new BuyTicket();
Thread thread1=new Thread(buyTicket,"小明");
Thread thread2=new Thread(buyTicket,"小红");
Thread thread3=new Thread(buyTicket,"黄牛");
thread1.start();
thread2.start();
thread3.start();
}
}
class BuyTicket implements Runnable{
private int ticket=10;
private boolean flag=true;
@Override
public void run() {
while(flag){
buy();
}
}
public synchronized void buy(){
while(ticket<=0){
flag=false;
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"拿到了"+ticket--);
}
}
锁块
锁住header 类
saveData(Header header){
//一些查询的业务操作
if(true){
}
synchronized (header){
//对Head表做修改增加的处理
}
//别的一些查询操作
}
死锁
案列
public class DeadLockDemo {
public static void main(String[] args) {
Make make=new Make(0,"安琪");
Make make2=new Make(1,"妲己");
make.start();
make2.start();
/* new Thread(new Make(0,"安琪")).start();
new Thread(new Make(0,"妲己")).start();*/
}
}
//口红
class Lipstick {
}
//镜子
class Mirror {
}
//化妆
class Make extends Thread{
//只有一个口红
static Lipstick lipstick=new Lipstick();
//只有一个镜子
static Mirror mirror=new Mirror();
int choice;//选择
String girlName;//女孩名称
public Make(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
makeup();
}
//化妆
private void makeup(){
if(choice==0){
synchronized (lipstick){
System.out.println(this.girlName+"获得口红的锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//睡眠一秒钟后去拿镜子
synchronized (mirror){
System.out.println(this.girlName+"获得镜子的锁");
}
}
}else{
synchronized (mirror){
System.out.println(this.girlName+"获得镜子的锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipstick){
System.out.println(this.girlName+"获得口红的锁");
}
}
}
}
}
防止死锁
// 不要锁互相保持持有的锁
//化妆
private void makeup(){
if(choice==0){
synchronized (lipstick){ // 多线程同时执行好多次类 难免会 同时走到 if 和else 里面 if里面不要持有口红的锁的时候 又去锁镜子,吧镜子锁放到外面 ,锁住口红的快包含了镜子,别人就 拿不到镜子了
System.out.println(this.girlName+"获得口红的锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//睡眠一秒钟后去拿镜子
synchronized (mirror){
System.out.println(this.girlName+"获得镜子的锁");
}
}else{
synchronized (mirror){
System.out.println(this.girlName+"获得镜子的锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (lipstick){
System.out.println(this.girlName+"获得口红的锁");
}
}
}
lock锁
核心代码
class TestLock{
int tickNum=10;
private final ReentrantLock lock=new ReentrantLock();
public void buy(){
lock.lock();
try {
//可以保证线程安全
}finally {
lock.unlock();
}
}
}
lock锁和synchronized 区别
案例
public class TestLockDemo {
public static void main(String[] args) {
TestLock testLock=new TestLock();
//三个线程
new Thread(()->{
testLock.buy();
}).start();
new Thread(()->{
testLock.buy();
}).start();
new Thread(()->{
testLock.buy();
}).start();
}
}
class TestLock{
int tickNum=10;
private final ReentrantLock lock=new ReentrantLock();
public void buy(){
lock.lock();
try {
while (true){
if(tickNum>0){
try {
Thread.sleep(1000);//睡眠就是为了等其他线程过来看看会不会同时抢
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"买到了第几个票:"+tickNum--);
}else{
return;
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
线程通信
基础讲解
标志位 案列 演员和观众
//演员表演完一个节目 观众观看完,演员继续表演,观众在观看
// this.wait() 等待表演, 观看完了 this.notifyAll(); //唤醒演员去表演 ,表演完,在唤醒观众去观看
public class TestPc {
public static void main(String[] args) {
Tv tv=new Tv();
new Player(tv).start();
new Watcher(tv).start();
}
}
//生产者 --》演员
class Player extends Thread{
Tv tv;
public Player(Tv tv){
this.tv=tv;
}
@Override
public void run(){
for (int i = 0; i < 20; i++) {
if(i%2==0){
this.tv.play("快乐大本营");
}else{
this.tv.play("B站生活");
}
}
}
}
//消费者--》观众
class Watcher extends Thread{
Tv tv;
public Watcher(Tv tv){
this.tv=tv;
}
@Override
public void run(){
for (int i = 0; i < 20; i++) {
this.tv.watch();
}
}
}
//TV
class Tv{
//演员表演, 观众等待 true
//观众观看 演员等待 false
String voice;//节目
boolean flag=true; //标志位
//表演
public synchronized void play(String voice){
if(!flag){
try {
this.wait(); //等待 不停止别的线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演员表演了:"+voice);
//通知观众观看
this.notifyAll(); //唤醒
this.voice=voice;
this.flag=!this.flag;
}
//观看
public synchronized void watch(){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观众观看:"+this.voice);
//通知演员表演
this.notifyAll();
this.flag=!this.flag;
}
}
线程池
释义
案列
//线程池
public class TestPoolDemo {
public static void main(String[] args) {
ExecutorService service= Executors.newFixedThreadPool(10);
service.execute(new Test1());
service.execute(new Test1());
service.execute(new Test1());
service.execute(new Test1());
service.execute(new Test1());
}
}
class Test1 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
异步和多线程
源码解释
https://www.cnblogs.com/dennyzhangdd/p/9026303.html#_label1_0
区别
https://blog.csdn.net/woliuyunyicai/article/details/45165869
https://zhuanlan.zhihu.com/p/92035904
异步调用注意
https://blade.blog.csdn.net/article/details/44648667?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-3.control
多线程调用
//多线程 批量增加 xml 500个一组
private void threadExecuteData(List<Item> saveList){
ExecutorService dataFileUploadExecutorService = ThreadConstants.getDataFileUploadExecutorService();
//500个分组执行
List<List<Item>> listSave = ListDeepCopy.splitTo(saveList, CompletePlanConstant.THREAD_NUM_DATA);
final CountDownLatch endGate = new CountDownLatch(listSave.size());
for (List<Item> deliveryCompleteMachineDetails : listSave) {
final List<Item> listDataThread=deliveryCompleteMachineDetails;
dataFileUploadExecutorService.execute(()->{
try {
itemMapper.insertBatchList(listDataThread);
}catch(Exception e){
throw new ServiceException("多线程增加异常,请联系管理员!");
}finally{
endGate.countDown();
}
});
}
try {
endGate.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//long entTime = System.currentTimeMillis(); //获取开始时间
// System.out.println((saveList.size()+updateList.size())+"条数据,处理时间:" + (entTime - startTimeUpdate) + "ms");
}
工具类
package org.springblade.delivery.plan.utils;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Description
* 配置参数常量类
*
* @author <a href="https://qiankunpingtai.cn">qiankunpingtai</a>
* @Date: 2019/6/17 16:38
*/
public class ThreadConstants {
/**
* 默认的日期格式
*/
public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
* 默认的分页起始页页码
*/
public static final Integer DEFAULT_PAGINATION_PAGE_NUMBER = 1;
/**
* 无数据时列表返回的默认数据条数
*/
public static final Long DEFAULT_LIST_NULL_NUMBER = 0L;
/**
* 默认的分页条数
*/
public static final Integer DEFAULT_PAGINATION_PAGE_SIZE = 10;
/**
* 每页数据条数的参数名
*/
public final static String PAGE_SIZE = "pageSize";
/**
* 每当前页码的参数名
*/
public final static String CURRENT_PAGE = "currentPage";
/**
* 超级管理员的登录名
*/
public final static String ADMIN_USER_NAME = "admin";
/**
* 十六进制默认前补位字符串
*/
public final static String HEX_DEFAULT_INSERT_STRING = "0";
/**
* excle导入时,默认一次操作数据库的数据条数
*/
public static final int IMPORT_ONCE_MAX_WRITE_SIZE = 50;
/**
* excle导入msisdn时,默认一次操作数据库的数据条数
*/
public static final int IMPORT_MSISDN_ONCE_MAX_WRITE_SIZE = 10;
/**
* 一个公共的队列,用来存放短信写卡请求
* */
/**
* 记录每一个线程的访问者
*/
public volatile static Map<String, Object> CROSS_INTERCEPTOR_VISIT_MAP;
public static final String CROSS_INTERCEPTOR_VISIT_MAP_STR = new String("cross_interceptor_visit");
public static Map<String, Object> getCrossInterceptorVisitMap() {
if (CROSS_INTERCEPTOR_VISIT_MAP == null) {
synchronized (CROSS_INTERCEPTOR_VISIT_MAP_STR) {
if (CROSS_INTERCEPTOR_VISIT_MAP == null) {
CROSS_INTERCEPTOR_VISIT_MAP = new ConcurrentHashMap<>();
}
}
}
return CROSS_INTERCEPTOR_VISIT_MAP;
}
/**
* 一个公共线程池,用来处理卡数据上传的处理过程
* 核心线程7个,最大线程数20,队列100,线程保有时间100S
*/
public static ExecutorService DATA_FILE_UPLOAD_EXECUTOR_SERVICE = null;
public static final String DATA_FILE_UPLOAD_EXECUTOR_SERVICE_STR = new String("data_file_upload");
public static ExecutorService getDataFileUploadExecutorService() {
if (DATA_FILE_UPLOAD_EXECUTOR_SERVICE == null) {
synchronized (DATA_FILE_UPLOAD_EXECUTOR_SERVICE_STR) {
if (DATA_FILE_UPLOAD_EXECUTOR_SERVICE == null) {
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(10000);
DATA_FILE_UPLOAD_EXECUTOR_SERVICE = new ThreadPoolExecutor(10, 30, 300, TimeUnit.SECONDS, workQueue);
}
}
}
return DATA_FILE_UPLOAD_EXECUTOR_SERVICE;
}
}