回顾java线程(基础篇)

java线程

传送门

为什么会出现多线程?

进程是程序执行的实体,每一个进程都是一个应用程序,cpu有多核,每个核心只能处理一件事,当多个进程,也就是多个程序运行的时候,cpu一般会通过时间片轮转调度的算法来实现多个进程的同时运行

若两个任务需要同时运行,必须要运行两个进程,由于每个进程会有自己的独立的内存空间,进程之间的通信变得很麻烦,而且不同进程之间执行会产生上下文切换,比较耗时,因此会提出能否在进程中执行多个任务?

线程问世, 一个进程会包含多个线程,线程是单一的顺序控制流程,到此,线程就变成了程序执行的最小单元,各线程之间可以共享该进程所在的内存空间,线程之间上下文切换也快于进程

一般情况下,main方法是单线程的执行,也就是计算、运行是同步的,如果我们想并行的计算,也就是异步计算,应该如何?这就需要多线程

线程怎么用?

这是一个例子,主线程先抢占到cpu资源

//code
public class Main {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50; i++) {
                System.out.println("线程A" + i);
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50; i++) {
                System.out.println("线程B" + i);
            }
        });
        t1.start();
        t2.start();
    }
}


//result
线程A0
线程B0
线程A1
线程A2
线程A3
线程B1
线程A4
......

线程生命周期

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8z0P63a9-1649165414982)(../ZNV/%E7%AC%94%E8%AE%B0%E5%9B%BE%E7%89%87/JUC/image-20220405164452185.png)]

线程处于运行状态下,下一个状态会是:就绪态、阻塞态、终止态

// code: 对于处于线程中断信号,不予处理,继续运行
public class Main {

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程开始运行");
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("发现中断信号,不管,继续运行");
                    Thread.interrupted(); //中断标记复位,也就是不管中断信号
                }
            }
        });
        t1.start();
        try {
            Thread.sleep(3000);
            t1.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
// code:线程暂停后继续运行,不推荐,会牵扯到死锁
public class Main {

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程开始运行");
            Thread.currentThread().suspend();
            System.out.println("线程继续运行");
        });
        t1.start();
        try {
            Thread.sleep(3000);
            t1.resume();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

线程优先级

因为资源问题,java内部事采用的线程抢占式调度,也就是优先级别越高,越优先使用cpu资源,一般分为三种:最低、最高、常规

// code:在某个执行时可以让位给其他线程
public class Main {

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程A开始运行");
            for (int i = 0; i < 50; i++) {
                if (i % 5 == 0) {
                    System.out.println("让位");
                    Thread.yield();
                }
            }
            System.out.println("线程A结束");
        });
        Thread t2 = new Thread(() -> {
            System.out.println("线程B开始运行");
            for (int i = 0; i < 50; i++) {
                System.out.println("线程B执行" + i);
            }
            System.out.println("线程B执行完毕");
        });
        t1.start();
        t2.start();
    }
}

// result
线程A开始运行
让位
线程B开始运行
让位
让位
线程B执行0
线程B执行1
线程B执行2
线程B执行3
线程B执行4
线程B执行5
让位
......

某个线程运行时,产生某个条件时,可以让另外一个线程先执行

// code:线程B执行=10时,会等待执行,让线程A全部执行完再去执行剩下的
public class Main {

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程A开始运行");
            for (int i = 0; i < 50; i++) {
                System.out.println("A计算" + i);
            }
            System.out.println("线程A结束");
        });
        Thread t2 = new Thread(() -> {
            System.out.println("线程B开始运行");
            for (int i = 0; i < 50; i++) {
                System.out.println("线程B执行" + i);
                if (i == 10) {
                    try {
                        System.out.println("线程A加入");
                        t1.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            System.out.println("线程B执行完毕");
        });
        t1.start();
        t2.start();
    }
}

线程同步

对于一公共线程可访问变量,对其修改不同步会导致数值异常,所以必须要保证该共享变量的原子性(要么全部执行成功,要么全部不执行

// code:共享变量值异常
public class Main {

    private static int value = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) value++;
            System.out.println("线程A结束");
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) value++;
            System.out.println("线程B结束");
        });
        t1.start();
        t2.start();
        Thread.sleep(1000);
        System.out.println(value);
    }
}

通过synchronized同步代码块,必须要同一锁,也就是同一对象

// code:悲观锁
public class Main {

    private static int value = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (Main.class) {
                    value++;
                }
            }
            System.out.println("线程A结束");
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (Main.class) {
                    value++;
                }
            }
            System.out.println("线程B结束");
        });
        t1.start();
        t2.start();
        Thread.sleep(1000);
        System.out.println(value);
    }
}
// code:不同锁,值异常
public class Main {

    private static int value = 0;

    public static void main(String[] args) throws InterruptedException {
        Main main1 = new Main();
        Main main2 = new Main();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (main1) {
                    value++;
                }
            }
            System.out.println("线程A结束");
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (main2) {
                    value++;
                }
            }
            System.out.println("线程B结束");
        });
        t1.start();
        t2.start();
        Thread.sleep(1000);
        System.out.println(value);
    }
}

死锁的情况

public class Main {

    public static void main(String[] args) throws InterruptedException {
        Object o1 = new Object();
        Object o2 = new Object();

        Thread t1 = new Thread(() -> {
            synchronized (o1) {
                try {
                    Thread.sleep(1000);
                    synchronized (o2) {
                        System.out.println("线程A");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (o2) {
                try {
                    Thread.sleep(1000);
                    synchronized (o1) {
                        System.out.println("线程B");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

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

wait、notify、notifyAll方法执行,

public class Main {

    public static void main(String[] args) throws InterruptedException {
        Object o1 = new Object();

        Thread t1 = new Thread(() -> {
            synchronized (o1) { //对象作为锁
                try {
                    System.out.println("A开始等待");
                    o1.wait(); //进入等待状态并释放锁
                    System.out.println("A等待结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (o1) {
                System.out.println("B被唤醒");
                o1.notify(); //唤醒处于等待状态的线程
                o1.notifyAll(); //notifyAll是唤醒全部
                for (int i = 0; i < 50; i++) {
                    System.out.println(i);
                }
                //执行完后,释放锁,等待状态的线程拿到锁才能执行
            }
        });

        t1.start();
        Thread.sleep(1000);
        t2.start();
    }
}

// result 
A开始等待
B开始执行
0
1
......
48
49
A等待结束

ThreadLocal

线程自己单独空间存放变量值

// code:其他线程无法获取自己线程空间的变量
public class Main {

    public static void main(String[] args) throws InterruptedException {
        ThreadLocal<String> local = new ThreadLocal<>();
        Thread t1 = new Thread(() -> {
            local.set("xiao");
            System.out.println("已给值");
            System.out.println(local.get());
        });

        Thread t2 = new Thread(() -> {
            System.out.println(local.get());
        });

        t1.start();
        Thread.sleep(3000);
        t2.start();

    }
}

// result
已给值
xiao
null

子线程无法获取父线程的ThreadLocal值?

// code:InheritableThreadLocal可以让子线程拿到父线程的变量
public class Main {

    public static void main(String[] args) throws InterruptedException {
        ThreadLocal<String> local = new InheritableThreadLocal<>();
        Thread t1 = new Thread(() -> {
            local.set("xiao");
            new Thread(()->{
                System.out.println(local.get());
            }).start();
        });
        t1.start();
    }
}

定时器

自定义

public class Main {

    public static void main(String[] args) throws InterruptedException {
        //new TimeTask(() -> System.out.println("定时任务"), 3000).start();
        new TimeLoopTask(() -> System.out.println("定时任务"), 1000).start();
    }

    static class TimeTask {
        Runnable task;
        long time;

        public TimeTask(Runnable task, long time) {
            this.task = task;
            this.time = time;
        }

        public void start() {
            new Thread(() -> {
                try {

                    Thread.sleep(time);
                    task.run(); //休眠后再运行

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    static class TimeLoopTask {
        Runnable task;
        long looptime;

        public TimeLoopTask(Runnable task, long looptime) {
            this.task = task;
            this.looptime = looptime;
        }

        public void start() {
            new Thread(() -> {
                try {
                    while (true) {
                        Thread.sleep(looptime);
                        task.run(); //休眠后再运行
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

java自带Timer类进行定时任务调度

public class Main {

    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer(); //创建定时器对象
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
                timer.cancel(); //结束进程
            }
        }, 1000); //延时执行任务
    }
}

守护线程

// code:父线程是守护线程,子线程也会跟着结束
public class Main {

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            Thread it = new Thread(() -> { //子线程
                while (true) {
                    try {
                        System.out.println("正常运行");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            it.start();
        });

        t.setDaemon(true); //设置为守护线程
        t.start();
        for (int i = 0; i < 5; i++) {
            Thread.sleep(1000);
        }

    }
}

集合并行方法

public class Main {

    public static void main(String[] args) throws InterruptedException {
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 5, 8, 3, 4));
        list
                .parallelStream() //并行流
                //forEachOrdered 单线程,是有序的
                .forEach(i -> System.out.println(Thread.currentThread().getName() + "->" + i));
    }
}

生产者消费者

public class Main {


    private static final List<Object> list = new ArrayList<>();

    public static void main(String[] args) throws InterruptedException {

        Thread c1 = new Thread(Main::add);
        c1.setName("生产A");
        Thread c2 = new Thread(Main::add);
        c2.setName("生产B");

        c1.start();
        c2.start();

        Thread s1 = new Thread(Main::take);
        s1.setName("消费A");
        Thread s2 = new Thread(Main::take);
        s2.setName("消费B");
        Thread s3 = new Thread(Main::take);
        s3.setName("消费C");

        s1.start();
        s2.start();
        s3.start();
    }

    private static void add() {
        while (true) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (list) {
                list.add(new Object());
                System.out.println(new Date() + Thread.currentThread().getName() + "已生产");
                list.notify();
            }
        }

    }

    private static void take() {
        while (true) {
            try {
                synchronized (list) {
                    while (list.isEmpty()) { //循环判断是否为空,空的情况就不能去取
                        list.wait();
                    }
                }
                Thread.sleep(4000);
                System.out.println(new Date() + Thread.currentThread().getName() + "已消费");
                list.remove(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

友培

数据皆开源!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值