JAVA多线程

关于多线程

一、开启线程的三种方法

1.创建一个继承Thread的线程类
public class MyThread extends Thread {
    @Override
    public void run() {
        //线程任务
    }
}

MyThread thread = new MyThread();
thread.start();
2.实现Runnable接口
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        //线程任务
    }
}
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();

与继承的方式相比,实现Runnable接口有如下优势:
1.通过给线程分配任务的方式,更适合多个线程同时执行的情况
2.避免单继承的局限性
3.任务和线程本身分离,提高程序的健壮性
4.线程池接受Runnable类型的任务,不能接受Thread类型线程

3.带返回值的Callable
public class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        Thread.sleep(1000);
        return 100;
    }
}
Callable<Integer> c = new MyCallable();
FutureTask task = new FutureTask(c);
new Thread(task).start();
task.get();//获取返回值

二、守护线程和用户线程

在所有的用户线程都执行完毕,守护线程才会结束。只要有一个用户线程存在,那么所有的守护线程都不能关闭。
main方法线程是用户线程,当main线程结束,JVM不一定会退出,main线程并不一定是最后退出的线程。

三、线程常见操作(方法)

stop()。方法已经过时不再使用,本质上并不安全。
Thread.currentThread()获取当前线程。
Thread.sleep()
interrupter(),触发中断标记,进入catch(InterrupterException)块,此时现在仍然继续执行,如果要中断,在catch块中return。
wait()
notify()/notifyAll()

四、解决线程安全的三种方法

1.同步代码块(Synchronized),线程观察同一把锁,程序员自己创建锁对象
2.同步方法,非静态,锁对象就是this对象,静态则是类名.class
3.显式锁(默认非公平锁)

Lock l = new ReentrantLock(true);//true参数表示公平锁
l.lock();//加锁
l.unlock();//解锁

五、生产者和消费者问题

https://www.jianshu.com/p/ab013a4d5878

六、线程的六种不同状态

1.new,线程创建,尚未启动
2.runnable,线程启动,在JVM中执行
3.blocked,被阻塞等待监视器锁定
4.waiting,等待唤醒,没有唤醒一直等待
5.timedWaiting,计时等待,时间到等待结束
6.terminated线程结束

七、四种线程池技术

1.缓存线程池

ExecutorService service = Executors.newCachedThreadPool();
service.execute(...);

2.定长线程池

ExecutorService service = Executors.newFixedThreadPool(2);//固定2个线程
service.execute(...);

3.单线程线程池

ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(... );

4.周期定长线程池

ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
service.schedule(...);
service.scheduleAtFixedRate(...);

阿里巴巴规约,自己需要手动创建线程池,不要使用Executors创建,原因是:
CachedThreadPool
允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
解决办法:

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                    60L, TimeUnit.SECONDS,
                                    new SynchronousQueue<Runnable>());
}

FixedThreadPool或者SingleThreadPool 允许的请求队列长度为Integer.MAX_VALUE,可能大量堆积请求,同样会导致OOM异常。
解决办法:

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>());
}
 
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

生产环境的做法:

  1. 创建线程工厂,指定创建线程时的线程名称的命名规律
ThreadFactory nameThreadFactory = new ThreadFactoryBuilder().setNameFormat(“demo-pool-%d”).build();
  1. 创建线程池 线程池在创建时可以不人为指定线程工厂,默认使用的是DefaultThreadFactory

/**
 * 各参数含义
 * corePoolSize    : 线程池中常驻的线程数量。核心线程数,默认情况下核心线程会一直存活,即使处于闲置状态也不会 
 *                   受存活时间 keepAliveTime 的限制,除非将 allowCoreThreadTimeOut 设置为 true。
 * maximumPoolSize : 线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的
 *                         LinkedBlockingQueue时,这个值无效。
 * keepAliveTime   : 当线程数量多于 corePoolSize 时,空闲线程的存活时长,超过这个时间就会被回收
 * unit            : keepAliveTime 的时间单位
 * workQueue       : 存放待处理任务的队列
 * threadFactory   : 线程工厂
 * handler         : 拒绝策略,拒绝无法接收添加的任务
 */
ExecutorService pool1 = new ThreadPoolExecutor(
5, 200, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1024));

也可以手动指定线程工厂

ExecutorService pool2 = new ThreadPoolExecutor(
5, 200 ,0L, TimeUnit.MILLISECONDS, 
new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, 
new ThreadPoolExecutor.AbortPolicy());
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值