栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java多线程编程总结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java多线程编程总结

并发与并行

类比在KTV唱歌,并发就是几个人轮流用一个麦克风,并行就是每人都有一个麦克风。

实现多线程的方式

继承Thread类

重写父类Thread的run方法,然后在其他地方实例化该类,并调用该对象的start方法,即启动此线程。

public class TestThread1 extends Thread{
    
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码。。。" + i);
        }
    }

    public static void main(String[] args) {
        TestThread1 testThread1 = new TestThread1();
        testThread1.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习。。。" + i);
        }
    }
}

实现Runnable接口

实现Runnable的run方法,在其他地方,实例化该对象,并实例化Thread类,传入该对象,然后调用Thread对象的start方法。

public class TestThread3 implements Runnable{
    
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码。。。" + i);
        }
    }

    public static void main(String[] args) {
        TestThread3 testThread3 = new TestThread3();

        Thread thread = new Thread(testThread3);
        thread.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习。。。" + i);
        }
    }
}

另外,使用这种方式,也可以直接传入Lambda表达式,因为Thread的一个构造方法传入的是Runnable接口对象,且Runnable接口只有一个抽象方法。

public class TestThread4{

    public static void main(String[] args) {

        new Thread(() -> System.out.println("我在看代码。。。")).start();
    }
}

实现Callable接口

已很少使用

线程状态

 线程休眠sleep

(抱着锁睡),线程从运行到阻塞,让出cpu使用权。

线程礼让yield

让出cpu使用权,但可能由于cpu调度算法,马上又获取到cpu使用权。

线程强制执行join

直接执行该线程(插队),其他线程阻塞,直到该线程运行完毕。

守护线程

JVM不用带单守护线程执行完毕,如后台记录操作日志,监控内存,垃圾回收等待;

设置线程对象的daemon为true,则当其他线程运行完毕,此线程也会结束(会伴有一定的延迟)。

线程同步

多个线程操作同一个资源。

synchronized

每一个对象都有一个锁(sleep不会释放锁),当一个线程获得对象的排他锁(使用关键字synchronized),独占资源,其他线程必须等待。使用后释放锁即可。

可以使用同步方法与同步块两种方式。

死锁

多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,从而导致线程都停止运行。

某一个同步块同时拥有“两个以上对象的锁“时,就可能会发送“死锁”问题。

Lock锁

显示定义同步锁。

// 可重入锁
ReentrantLock lock = new ReentrantLock();
// 加锁
lock.lock();
// 解锁
lock.unlock();

线程池

ThreadPoolExecutor

构造函数的7个参数

    int corePoolSize:表示常驻核心线程数;int maximumPoolSize:表示线程能够容纳同时执行的最大线程数;long keepAliveTime:表示线程池中的线程空闲事件,当空闲时间达到keepAliveTime值时,线程会被销毁,知道只剩下corePoolSize个线程为止;TimeUnit unit:表示事件单位,一般为秒;BlockingQueue workQueue:表示缓存队列,当前请求的线程数大于maximumPoolSize时,线程进入BlockingQueue阻塞队列;ThreadFactory threadFactory:表示线程工厂,用来生产一组相同任务的线程;RejectedExecutionHandler handler:表示执行拒绝策略的对象;自带静态类:
      ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常;ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常;ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程);ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 ;

线程池不允许使用Exectors,而是通过ThreadPoolExecutor的方式创建,这样的处理方式能更加明确线程池的运行规则,规避资源耗尽的风险。

ThreadLocal

ThreadLocal是用来隔离不同线程间的相同变量。

public class TestThreadLocal {
    static ThreadLocal threadLocal = new ThreadLocal<>();

    public static void main(String[] args) throws InterruptedException {
        // 设置两个线程,分别设置自己的ThreadLoacal,观察是否互相影响
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                if (i == 0) threadLocal.set(100);
                else {
                    System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
                    threadLocal.set(100 + i);
                }
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                if (i == 0) threadLocal.set(200);
                else {
                    System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
                    threadLocal.set(200 + i);
                }
            }
        });

        t1.start();
        t2.start();
    }
}

输出结果如下,可以看到线程1和线程2的输出变量是相互隔离的。 

可以根据实际变量的情况来命名threadLocal的名字。

三个重要方法
    set():如果没有set操作的ThreadLocal,容易引起脏数据问题;get():始终没有get操作的ThreadLocal对象是没有意义的;remove():如果没有remove操作,容易引起内存泄漏;
脏数据

线程池中使用ThreadLocal会产生这个问题,如果某个线程不显示调用remove()方法,且下一个线程不调用set()设置初始值,则可能get()到重用的线程信息。

内存泄漏

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/782828.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号