多线程学习总结

一、多线程的应用场景
1.1 向第三方系统推送数据
对于没有关联的大量数据推送,可以引入多线程进行并发操作,降低数据推送的时间,提供数据推送的实时性。
重点:防止重复、失败机制、线程创建选择
1.2 银行存取款
对于从多个渠道对账户余额变动的操作,需要进行多线程同步,防止变量值或对象状态出现混乱。
1.3 异步的接口调用
对于在主逻辑之外需要进行一些消息推送或者是数据推送,可以异步调用接口,主逻辑继续执行,在主逻辑完成后再等待或等待一定时间后结束。
二、线程的创建方法
2.1 继承Thread创建线程

public class SubClass extends Thread {
    @Override
    public void run() {
        System.out.println(getName() + "SubClass is running");
    }
}
// 继承thread创建线程
System.out.println(Thread.currentThread().getName());
System.out.println("继承thread类创建线程");
SubClass subClass = new SubClass();
subClass.start();

2.2 实现Runnable接口创建线程

public class SubClass1 implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "SubClass1 is running");
    }
}

// 继承Runnable创建线程
System.out.println("实现Runnable接口创建线程");
SubClass1 subClass1 = new SubClass1();
new Thread(subClass1).start();

2.3 利用Callable和FutureTask创建有返回值的线程

public class SubClass2 implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getName() + "is Running");
        String str = "SubClass2执行完毕";
        return str;
    }
}
// 通过callable和futureTask创建线程
System.out.println("通过callable和futureTask创建线程");
SubClass2 subClass2 = new SubClass2();
FutureTask futureTask = new FutureTask(subClass2);
new Thread(futureTask).start();
if (futureTask.isDone()) {
    System.out.println("返回值:" + futureTask.get());
} else {
    System.out.println("任务还没完成,继续跑");
    System.out.println("返回值:" + futureTask.get());
}

2.4 利用线程池创建线程
创建线程池推荐使用ThreadPoolExecutor 类, 线程工厂推荐使用google提供的guava包中的ThreadFactoryBuilder类创建。线程池参数意义:
// corePoolSize:核心池的大小,
// maximumPoolSize:线程池最大线程数
// keepAliveTime:线程保持活跃的时间.当线程池中线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,
// 直到线程池中的线程不超过keepAliveTime
// unit:keepAliveTime的时间单位
// workQueue:阻塞队列。被提交,但尚未被执行的队列
// threadfactory:线程工厂
// policy:策略,当线程池处于饱和时,使用某种策略处理任务提交。默认abortPolicy表示抛出异常
// 有新任务到达,如果当前线程数小于corePoolsize,则创建线程
// 如果当前线程数超过corePoolsize,则放入等待队列;
// 若等待队列满了,且线程数小于maximumPoolsize则创建线程
// 如果等待队列满了,且线程数达到maximumPoolsize,则抛异常

//通过线程池创建线程
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("testThread" + "-%d").build();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_NUM, MAX_POOL_NUM, KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue(WORK_QUEUE_CAPACITY), threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
for(int i = 0; i < 10 ; i++) {
    MyRunnable myRunnable = new MyRunnable("" + i);
    threadPoolExecutor.execute(myRunnable);
}
// 终止线程池
threadPoolExecutor.shutdown();
while(!threadPoolExecutor.isTerminated()) {
    //System.out.println("线程池咋还没关??");
}
System.out.println("终止线程池了");

三、多线程编程的debug方法
3.1 多线程如何打断点,为
了方便对每一个子线程中的内容进行调试,分别在主线程和子线程中打断点。如下图所示:
在这里插入图片描述
两个断点都需要如下设置:
在断点处点击鼠标右键,设置suspend为Thread。
在这里插入图片描述
这样可以选择线程进行调试
四、多线程编程的注意事项
4.1 线程池大小的确定
一般情况下,我们使用如下简单粗暴的公式来确定线程数量。N为CPU核心数。
CPU密集型任务:N+1
I/O密集型任务:2N
4.2 线程池创建的选择
暂不分析,还不够了解
4.3 线程池中线程的命名
线程的命名关系到以后问题排查,因此取一些有意义的名字是一个理智的选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值