Java多线程(基础认知与代码测试)

本文详细介绍了Java多线程的基本概念、实现方式、线程状态管理、线程同步和死锁问题,以及线程通信和线程池的使用。通过实例分析,解释了线程同步中的synchronized和Lock锁的差异,并探讨了Lambda表达式在多线程中的应用。
摘要由CSDN通过智能技术生成

Java多线程

线程简介

想要学习线程就不得不先了解进程和线程的关系

线程及一个进程中的多个子任务,例如电脑中打开了一个视频播放器(一个进程),该播放器会进行画面、声音、字幕等多个子任务(多个线程),在Java语言中线程就是独立的执行路径。

核心概念:

  • 在程序运行时,即视没有自己创建线程,后台也会有多个线程,如主线程、gc线程(垃圾回收);
  • main()称之为主线程,为系统的入口,用于执行整个程序;
  • 在一个进程中,如果开辟了多个线程,线程的运行有调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的干预的
  • 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;
  • 线程会带来额外的开销,如cpu调度时间,并发控制开销。
  • 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

线程实现

线程的创建

三种不同的实现方式:

  • 继承Thread类
package com.jerry.threadTest;

/**
 * Created by JerrySmith on 2022/3/24.
 *
 * 如何创建一个多线程
 *
 */
//方式一:继承Thread类,并重写run()方法,调用start开启线程
public class Test01 extends Thread {
   
    @Override
    public void run() {
   
        //run方法线程体
        for (int i = 0; i < 10; i++) {
   
            System.out.println("我在学习多线程"+i);
        }
    }

    public static void main(String[] args) {
   
        //主方法main线程
        Test01 test01 = new Test01();
        //使用start()方法开启线程
        test01.start();
        for (int i = 0; i < 10; i++) {
   
            System.out.println("我是main线程"+i);
        }
    }
}
/**
 * 我是main线程0
 我是main线程1
 我是main线程2
 我是main线程3
 我是main线程4
 我在学习多线程0
 我是main线程5
 我是main线程6
 我是main线程7
 我在学习多线程1
 我是main线程8
 我是main线程9
 我在学习多线程2
 我在学习多线程3
 我在学习多线程4
 我在学习多线程5
 我在学习多线程6
 我在学习多线程7
 我在学习多线程8
 我在学习多线程9


 从执行结果来看,两个线程同步进行,cpu交叉调度
 注意,线程开启不一定立即执行,由cpu分配调度
 * */
  • 实现Runnable接口
package com.jerry.threadTest;

/**
 * Created by JerrySmith on 2022/3/24.
 *
 * 创建线程方式二:实现Runnable接口
 *
 */
public class Test02 implements Runnable{
   

    public static void main(String[] args) {
   
        //创建实现Runnable接口类的对象
        Test02 test02 = new Test02();
        //创建一个线程对象 把实现了Runnable接口类的对象丢进去
        Thread thread = new Thread(test02);
        //使用线程对象的start()方法开启线程
        thread.start();
        for (int i = 0; i < 10; i++) {
   
            System.out.println("我是main方法"+i);
        }

    }

    /**
     * 重写了Runnable接口中的run方法
     */
    @Override
    public void run() {
   
        for (int i = 0; i < 10; i++) {
   
            System.out.println("我是run方法"+i);
        }
    }
}

  • 实现Callable接口(不常用)
package com.jerry.threadTest;

import java.util.concurrent.*;

/**
 * Created by JerrySmith on 2022/3/24.
 *
 * 实现Callable接口
 *
 */
public class Test05 implements Callable<Boolean>{
   


    @Override
    public Boolean call() throws Exception {
   
        for (int i = 0; i < 10; i++) {
   
            System.out.println("我是call方法");
        }
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
   
        //创建线程类的对象
        Test05 test05 = new Test05();
        //创建执行服务器
        ExecutorService service = Executors.newFixedThreadPool(1);//nThreads:线程数

        //提交执行
        Future<Boolean> sr = service.submit(test05);

        //获取结果
        Boolean aBoolean = sr.get();
        
        System.out.println(aBoolean);

        //关闭服务
        service.shutdown();
    }
}

初始线程并发问题

代码演示:《买票》10张票,小明、老师、黄牛党一起买

package com.jerry.threadTest;

/**
 * Created by JerrySmith on 2022/3/24.
 *
 * 线程同步问题,代码测试
 * 《买票》
 *  黄牛党拿到了第10张票
 *  小明拿到了第9张票
 *  小明拿到了第8张票
 *  黄牛党拿到了第7张票
 *  小明拿到了第5张票
 *  黄牛党拿到了第6张票
 *  小明拿到了第4张票
 *  黄牛党拿到了第4张票
 *  小明拿到了第3张票
 *  黄牛党拿到了第3张票
 *  小明拿到了第2张票
 *  黄牛党拿到了第1张票
 *  
 *  不可能拿到同一张票,所有出现了线程并发的问题
 */
public class Test03 implements Runnable{
   

    private int votesNum = 10;


    @Override
    public void run() {
   

        while (true){
   
            if (votesNum<=0) {
   
                break;
            }
            try {
   
                Thread.sleep(200);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"拿到了第"+(votesNum--)+"张票");
        }
    }

    public static void main(String[] args) {
   
        Test03 test03 = new Test03();
        new Thread(test03,"小明").start();
        new Thread(test03+"老师").start();
        new Thread(test03,"黄牛党").start();
    }
}

线程状态

  • 新生状态:当使用关键词new一个线程的时候,线程处于新生状态
  • 就绪状态:使用star关键词启动线程后,线程会进入就绪状态,等待cpu的调度
  • 启动状态:当cpu调度到线程后,线程开始启用执行
  • 阻塞状态:当用户使用线程休眠或等待或同步锁定时,线程会进入阻塞状态,阻塞解除之后线程会再次回到就绪状态等待cpu的调度
  • dead:线程中断或者结束后,就会进入死亡状态,不可以再次启动
package com.jerry.threadTest;

/**
 * Created by JerrySmith on 2022/3/31.
 *
 * 测试线程状态
 *
 *
 */
public class StaTest {
   
    public static void main(String[] args) throws InterruptedException {
   
        //new一个线程对象,重写run方法
        Thread thread = new Thread(()->{
   
            for (int i = 0; i < 5; i++) {
   
                try {
   
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
            }
            System.out.println("线程执行了");
        });

        //检测线程的状态
        //未启动时
        Thread.State state = thread.getState();
        System.out.println(state);

        //启动后
        thread.start();
        state = thread.</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值