java线程详解(史上最全)

java线程详解(史上最全)根据本人多年从业以及学习经验,录制了一套最新的Java精讲视频教程,如果你现在也在学习Java,在入门学习Java的过程当中缺乏系统的学习教程,你可以加QQ群654631948领取下学习资料,面试题,开发工具等,群里有资深java老师做答疑,每天也会有基础部分及架构的直播课,也可以加我的微信renlliang2013做深入沟通,只要是真心想学习Java的人都欢迎。java基础教程:https:…

大家好,又见面了,我是你们的朋友全栈君。

根据本人多年从业以及学习经验,录制了一套最新的Java精讲视频教程,如果你现在也在学习Java,在入门学习Java的过程当中缺乏系统的学习教程,你可以加QQ群654631948领取下学习资料,面试题,开发工具等,群里有资深java老师做答疑,每天也会有基础部分及架构的直播课,也可以加我的微信renlliang2013做深入沟通,只要是真心想学习Java的人都欢迎。

java基础教程:https://ke.qq.com/course/149432?tuin=57912c43

Java分布式互联网架构/微服务/高性能/springboot/springcloud:

https://ke.qq.com/course/179440?tuin=57912c43

  1. 线程的创建方式
    1. 继承Thread类

子类要重写run方法。

public class MyThread extends Thread {

    private String name;

    public MyThread(String name){
        this.name = name;
    }

    /**
     * 这就是线程执行的逻辑体
     */
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(name+"下载了"+i+"%");
        }
    }
}

测试代码:

public class ThreadTest {

    public static void main(String[] args) {
        //创建一个线程的对象
        MyThread mt = new MyThread("肖申克的救赎");
        //启动一个线程
        mt.start();
 //创建一个线程的对象
        MyThread mt1 = new MyThread("当幸福来敲门");
        //启动一个线程
        mt1.start();


        //System.out.println("方法结束");

    }
}
  1.  1.2实现Runnable接口来创建线程

示例代码

public class DownLoad implements Runnable {

    private String name;

    public DownLoad(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(name+"下载了"+i+"%");
        }
    }
}

测试代码:

public class ThreadTest {

    public static void main(String[] args) {
        //创建线程对象
        Thread t = new Thread(new DownLoad("肖申克的救赎"));
        Thread t1 = new Thread(new DownLoad("当幸福来敲门"));
        t.start();
        t1.start();
    }
}

 

2.线程的执行原理

java线程详解(史上最全)

 

3.线程生命周期

1.新建: 线程被new出来

2.准备就绪:线程具有执行的资格,即线程调用了start(),没有执行的权利

3.运行:具备执行的资格和具备执行的权利

4.阻塞:没有执行的资格和执行权利

5.销毁: 线程的对象变成垃圾,释放资源。

java线程详解(史上最全)

 4.并发

互联网的项目中存在着大量的并发的案例,如卖火车票,电商网站。

范例:火车站有100张票,4个窗口同时买票。

分析:4个窗口是4个线程同时在运行,100票是4个线程的共享资源。

java线程详解(史上最全)

语法:

synchronized(锁对象){

//操作共享资源的代码

}

同步代码加在什么地方?

1.代码被多个线程访问

2.代码中有共享的数据

3.共享数据被多条语句操作。

public class SaleTicketThread extends Thread {

    private String name;

    /**
     * 定义共享的数据100张票
     */
    static int tickets = 100;

    //创建一个锁对象,这个对象是多个线程对象共享的数据
    static Object obj = new Object();


    public SaleTicketThread(String name) {
        this.name = name;


    }

    @Override
    public void run() {

        //卖票是持续的
        while (true){

            synchronized (obj){
                if(tickets > 0){
                    System.out.println(name+"卖出座位是"+(tickets--)+"号");
                }else{
                    break;
                }
            }

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        System.out.println(name+"卖票结束");
  }
}

测试代码:

public class ThreadTest {

    public static void main(String[] args) {
        SaleTicketThread t1 = new SaleTicketThread("窗口1");
        SaleTicketThread t2 = new SaleTicketThread("窗口2");
        SaleTicketThread t3 = new SaleTicketThread("窗口3");
        SaleTicketThread t4 = new SaleTicketThread("窗口4");

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

第二种同步处理

public class SaleTicket implements Runnable {
    /**
     * 多个线程共享的100张票
     */
    int tickets = 100;

    //创建一个锁对象,这个对象是多个线程对象共享的数据
    Object obj = new Object();

    @Override
    public void run() {
        //卖票是持续的
        while (true){
            synchronized (obj){
                if(tickets > 0){
                    System.out.println(Thread.currentThread().getName()+"卖出座
位是"+(tickets--)+"号");
                }else{
                    break;
                }
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        System.out.println(Thread.currentThread().getName()+"卖票结束");
    }


}

测试代码

public class ThreadTest {

    public static void main(String[] args) {
        //创建一个卖票的对象
        SaleTicket st = new SaleTicket();

        Thread t1 = new Thread(st, "窗口1");
        Thread t2 = new Thread(st, "窗口2");
        Thread t3 = new Thread(st, "窗口3");
        Thread t4 = new Thread(st, "窗口4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();


    }
}

  

1.3Synchronized如果放在对象方法上

public class SaleTicket implements Runnable {
    /**
     * 多个线程共享的100张票
     */
    int tickets = 100;

    //创建一个锁对象,这个对象是多个线程对象共享的数据
    Object obj = new Object();

    @Override
    public void run() {
        //卖票是持续的
        while (true){
            if(saleTickets()){
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        System.out.println(Thread.currentThread().getName()+"卖票结束");
    }


    /*public boolean saleTickets(){
        synchronized (obj){
            boolean isFinish = false;
            if(tickets > 0){
                System.out.println(Thread.currentThread().getName()+"卖出座位是"+(tickets--)+"号");
            }else{
                isFinish = true;
            }
            return isFinish;
      }
    }*/

    /**
     *
     * @return     如果一个对象方法上有synchronized的话那么锁的对象就是this
     */
    public synchronized boolean saleTickets(){
        //synchronized (obj){
        boolean isFinish = false;
        if(tickets > 0){
            System.out.println(Thread.currentThread().getName()+"卖出座位是"+(tickets--)+"号");
        }else{
            isFinish = true;
        }
        return isFinish;
        //}
    }
}

Synchronized如果在类方法上那么锁对象就是类的类对象

public class SaleTicketThread extends Thread {

    private String name;

    /**
     * 定义共享的数据100张票
     */
    static int tickets = 100;

    //创建一个锁对象,这个对象是多个线程对象共享的数据
    static Object obj = new Object();


    public SaleTicketThread(String name) {
        super(name);
        this.name = name;


    }
  @Override
    public void run() {

        //卖票是持续的
        while (true){
            if(saleTickets()){
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        System.out.println(name+"卖票结束");
    }


    public static synchronized boolean saleTickets(){

        boolean isFinish = false;
        if(tickets > 0){
            System.out.println(Thread.currentThread().getName()+"卖出座位是"+(tickets--)+"号");
        }else{
            isFinish = true;
        }
        return isFinish;

    }
}

 测试代码:

public class ThreadTest {

    public static void main(String[] args) {
        SaleTicketThread t1 = new SaleTicketThread("窗口1");
        SaleTicketThread t2 = new SaleTicketThread("窗口2");
        SaleTicketThread t3 = new SaleTicketThread("窗口3");
        SaleTicketThread t4 = new SaleTicketThread("窗口4");
  t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

 

5.休眠

在做服务器端的程序的时候都需要给一个休眠的时间,在没有synchronized代码块里面会让出cpu的资源。

public static void main(String[] args) {
    while(true){
        System.out.println(new Date());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

休眠在同步代码块内不会让出cpu

synchronized (ojb){
    try {

        //我们休眠如果在synchronized内部就不会让出cpu的资源
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

 6.线程间的通信

java线程详解(史上最全)

 

生产者生成水果,如果水果没有被买走那么就不生产处于等待状态,如果水果被消费者买走这时候消费者会通知生产者告诉他我们已经把水果买走了请生产,消费者同理,如果水果已经生产出来那么就买走,买走之后再通知生产者水果已经没了请生产。

注意:

1.线程间的通信共享数据一定要有同步代码块synchronized

2.一定要有wait和notify,而且二者一定是成对出现。

3.生产者和消费者的线程实现一定是在while(true)里面

 

第一种实现方式:

public class Basket {


    private boolean isEmpty;

    public boolean isEmpty() {
        return isEmpty;
    }

    public void setEmpty(boolean empty) {
        isEmpty = empty;
    }
}

生产者:

public class Producer extends Thread {


    private Basket basket;

    public Producer(Basket basket){
  super();
        this.basket = basket;
    }

    @Override
    public void run() {

        while(true){
            //定义一个同步代码块
            synchronized (basket){
                try {
                    if(!basket.isEmpty()){
                        //线程等待的状态
                        basket.wait();
                    }
                    System.out.println("生成水果");
                    basket.setEmpty(false);
                    //通知在这个共享对象上等待的线程
                    basket.notify();

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


            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {


            }

        }
    }
}

消费者:

package cn.tx.demo8;

public class Consumer extends Thread{
 private Basket basket;

    public Consumer(Basket basket){
        super();
        this.basket = basket;
    }

    @Override
    public void run() {

        while(true){
            //定义一个同步代码块
            synchronized (basket){
                try {
                    if(basket.isEmpty()){
                        //线程等待的状态
                        basket.wait();
                    }
                    System.out.println("消费水果");
                    basket.setEmpty(true);
                        //通知在这个共享对象上等待的线程
                    basket.notify();

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


            }

        }
    }

}

线程的第二种实现方式实现runnable

public class Basket {
    private boolean isEmpty;

    public boolean isEmpty() {
  return isEmpty;
    }

    public void setEmpty(boolean empty) {
        isEmpty = empty;
    }
}

生产者

package cn.tx.demo9;

public class Producer implements Runnable {


    private Basket basket;

    public Producer(Basket basket){
        super();
        this.basket = basket;
    }

    @Override
    public void run() {

        while(true){
            //定义一个同步代码块
            synchronized (basket){
                try {
                    if(!basket.isEmpty()){
                        //线程等待的状态
                        basket.wait();
                    }
                    System.out.println("生成水果");
                    basket.setEmpty(false);
                    //通知在这个共享对象上等待的线程
                    basket.notify();

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


            }
  try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {


            }

        }
    }
}

消费者

package cn.tx.demo9;

public class Consumer implements Runnable{

    private Basket basket;

    public Consumer(Basket basket){
        super();
        this.basket = basket;
    }

    @Override
    public void run() {

        while(true){
            //定义一个同步代码块
            synchronized (basket){
                try {
                    if(basket.isEmpty()){
                        //线程等待的状态
                        basket.wait();
                    }
                    System.out.println("消费水果");
                    basket.setEmpty(true);
                        //通知在这个共享对象上等待的线程
                    basket.notify();

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

            }

        }
    }

}

测试:

public class Test {

    public static void main(String[] args) {
        Basket basket = new Basket();
        Producer producer = new Producer(basket);
        Consumer consumer = new Consumer(basket);

        Thread t = new Thread(producer);
        Thread t1 = new Thread(consumer);

        t.start();
        t1.start();
    }
}

 

 

7.线程的优先级

我们可以通过public final void setPriority(int newPriority)

来设置线程的优先级,但是优先级并不是绝对的,只是先对来说比其他的线程得到CPU的资源机会多一些。

public class ThreadTest {

    public static void main(String[] args) {
        //创建一个线程的对象
        MyThread mt = new MyThread("肖申克的救赎");
        //创建一个线程的对象
        MyThread mt1 = new MyThread("当幸福来敲门");

        mt.setPriority(Thread.MAX_PRIORITY);
     //启动一个线程
        mt.start();
        //启动一个线程
        mt1.start();

        //System.out.println("方法结束");

    }
}

 8.加入线程

join线程会抢先拿到CPU来执行线程,然后其他的线程再来执行

加入线程必须要在先执行的线程的start下面来执行

public class ThreadTest {

    public static void main(String[] args) {
        //创建一个线程的对象
        MyThread mt = new MyThread("肖申克的救赎");
        //创建一个线程的对象
        MyThread mt1 = new MyThread("当幸福来敲门");

        MyThread mt2 = new MyThread("魔戒1");

        mt.start();
        try {
            //加入线程必须要在先执行的线程的start下面来执行
            mt.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        mt1.start();

        mt2.start();
    }
}

 

 

9.让出线程

当前的线程从运行阶段回到就绪阶段,目的是把CPU的资源让给其他的线程。

public class MyThread extends Thread {

    private String name;

    public MyThread(String name){
        this.name = name;
    }
    /**
     * 这就是线程执行的逻辑体
     */
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(name+"下载了"+i+"%");
            //让出线程
            Thread.yield();
        }
    }
}

 10.守护线程

守护线程会随着主线程的结束而结束。

public class ThreadTest {

    public static void main(String[] args) {
        //创建一个线程的对象
        MyThread mt = new MyThread("肖申克的救赎");
        //设置守护线程
        mt.setDaemon(true);
        mt.start();
        System.out.println("主线程结束");
    }
}

 11.死锁

java线程详解(史上最全)

 

在做线程开发的时候要避免出现死锁。

死锁程序

public class DeadLockThread extends Thread {

    int flag;

    @Override
    public void run() {
        if(flag == 1){
            synchronized (Lock.lock1){
                System.out.println("进入锁1");
                synchronized (Lock.lock2){
                    System.out.println("进入锁1中的锁2");
                }
            }
        }else{
            synchronized (Lock.lock2){
                System.out.println("进入锁2");
                synchronized (Lock.lock1){
                    System.out.println("进入锁2中的锁1");
                }
            }
        }
    }
}

测试:

public class DeadLockTest {
 public static void main(String[] args) {
        DeadLockThread dt = new DeadLockThread();
        dt.flag = 1;
        DeadLockThread dt1 = new DeadLockThread();

        dt.start();
        dt1.start();

    }
}

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/156863.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • onpropertychange兼容示例[通俗易懂]

    [code="js"]//当状态改变的时候执行的函数functionhandle(){document.getElementById(‘msg’).innerHTML=’输入的文字长度为:’+document.getElementById(‘txt’).value.length;}//firefox下检测状态改变只能用oninput,且需要用addE…

    2022年4月9日
  • navivat 15在线激活码【中文破解版】

    (navivat 15在线激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月30日
  • C++ 序列化和反序列化

    C++ 序列化和反序列化序列化序列化1、背景2、定义3、序列化评价指标4、序列化实例参考序列化1、背景1、在TCP的连接上,它传输数据的基本形式就是二进制流,也就是一段一段的1和0。2、在一般编程语言或者网络框架提供的API中,传输数据的基本形式是字节,也就是Byte。一个字节就是8个二进制位,8个Bit。二进制流和字节流本质上是一样的。对于我们编写的程序来说,它需要通过网络传输的数据是结构化的数据,比如,一条命令、一段文本或者一条消息。对应代码中,这些结构化的数据都可以用一个类或者一个结构体来表示。序

    2022年6月17日
  • 压测工具jmeter怎么使用_并发压力测试工具

    压测工具jmeter怎么使用_并发压力测试工具一、Jmeter下载进入官网:http://jmeter.apache.org/1.第一步进入官网如下图2.选择进行下载,下载下来为一个压缩包,解压即可。3.我下载的是jmeter4.0版本,

    2022年8月2日
  • 2021年顶级编程语言名单出炉,SQL位居榜首,Java、Python紧随其后

    2021年顶级编程语言名单出炉,SQL位居榜首,Java、Python紧随其后不同的编程语言会对我们的求职产生相当大的影响,但是目前哪种编程语言最受公司欢迎呢?EmsiBurningGlass收集并分析了数百万个招聘信息,qizhon给SQL位居榜首,Java位列第二,Python排名第三。

    2022年10月5日
  • 简单描述时间轮_rocketmq 时间轮

    简单描述时间轮_rocketmq 时间轮时间轮作用也是用来作定时器触发任务,只是他更高效,时间复杂度为O(1)。运行原理为了方便理解我们参考钟表的形式,它分为3个层次:时、分、秒,只有秒钟在运动同样的,时间轮也分为多层,同样的只有第一层在运动,举个简单的4层时间轮例子(如下左图),我们假设最小计时单位为1(姑且理解为秒),用time来计时,初始为0,随着time递增,则:我们可以知道time应该落在第一层的位置intfirst_index=time%5当first_index==0,也就是第一层轮巡完毕,就需要将

    2022年9月30日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号