JAVA 多线程

线程:线程是操作系统能够进行运算调度的最小单位 被包含在进程当中 是进程中的实际运作单位

并发:在同一时刻,有多个指令在单个CPU上交替执行

并行:在同一时刻,有多个指令在多个CPU上同时执行

多线程实现的三种方式

1 继承Thread类

package com.qcby.MyThread01;

public class MyThread extends  Thread{

    public void run(){
        for(int i=0;i<100;i++){
            System.out.println("Hello World");
        }
    }
}

package com.qcby.MyThread01;

import com.qcby.MyThread01.MyThread;

public class ThreadDemo {


  /*
  多线程第一种定义方式
  1 自己定义一个类继承Thread
  2 重写run方法
  3 创建子类的对象 并启动线程
   */
   public static void main(String[] arges){
       MyThread p=new MyThread();
       p.start();
   }

}

2 实现Runnable接口

package com.qcby.Mythread02;

public class MyRun implements  Runnable{

    @Override
    public void run() {
        for(int i=0;i<100;i++){
            System.out.println("Hello");
        }
    }
}

package com.qcby.Mythread02;

public class ThreadDemo {

    /*
    1 自己定义一个类 实现Runnable接口
    2 重写里面的run方法
    3 创建自己的类的对象
    4 创建一个Thread对象  并开启线程
     */

    public static void main(String[] args) {
        MyRun p=new MyRun();
        Thread t=new Thread(p);
        t.start();

    }
}

3 实现Callable接口

package com.qcby.MyThread0;

import java.util.concurrent.Callable;

public class ThreadDemo implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int sum=0;
        for(int i=0;i<100;i++) {
            sum+=i;
        }
        return sum;
    }
}

package com.qcby.MyThread0;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class MyThread {

    /*

    1创建一个Callable类实现Callable接口
    2 重写call(有返回值的  表示多线程运行结果)
    3 创建Callable的对象(表示多线程要执行的任务)
    4 创建FutureTask的对象(作用管理多线程运行的结果)
    5 创建Thread对象 并启动
     */
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //表示多线程要执行的任务
        ThreadDemo mc=new ThreadDemo();
        //作用管理多线程运行的结果
        FutureTask<Integer> f=new FutureTask<>(mc);
        //创建线程对象
        Thread p=new Thread(f);
        p.start();
        System.out.println(f.get());
    }
}

三种方式的对比

常见的成员方法

线程的声明周期

同步代码块:

格式 synchronized(锁){

操作共享数据的代码

}

特点1 锁默认打开 有一个线程进去了 锁自动关闭

特点2 里面的代码全部执行完毕 线程出来后 锁自动打开

Lock锁:

JDK5以后提供 实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作

Lock是接口 不能直接实例化 采用它的实现类 ReentrantLock来定义实例化

等待唤醒机制:生产者消费者模式是一个十分经典的多线程协作的模式

案例

package com.qcby.MyThread03;

public class Foodie extends  Thread{

    @Override
    public void run(){
        while (true){
            synchronized (Desk.lock){
                if(Desk.count==0){
                    break;
                }else{
                    if(Desk.FoodFlag!=0){
                        try {
                            Desk.lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else{
                        System.out.println("厨师做了一碗面条");
                        Desk.FoodFlag=1;
                        Desk.lock.notifyAll();
                    }
                }
            }
        }
    }
}

package com.qcby.MyThread03;

import sun.security.krb5.internal.crypto.Des;

import java.time.DayOfWeek;

public class Cook extends Thread{

    @Override
    public void run(){
        /*
        1 循环
        2 同步代码块
        3 判断共享数据是否到了末尾(到了末尾)
        4 判断共享数据是否到了末尾(没有)
         */

        while (true){
            synchronized (Desk.lock){
                if(Desk.count==0){
                    break;
                }else{
                    if(Desk.FoodFlag==0){
                        try {
                            Desk.lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else{
                        Desk.count--;
                        System.out.println("吃货还能再吃面条"+ Desk.count+"碗!!");
                        Desk.lock.notifyAll();
                        Desk.FoodFlag=0;
                    }
                }
            }
        }
    }
}

Desk类用来控制生产者和消费者执行的代码

package com.qcby.MyThread03;

public class Desk {
    /*
    控制生产者 消费者的执行
     */
    // 0代表还没有做出来  1代表做出来的饭菜
    public static int FoodFlag=0;

    //总个数

    public static int count=10;

    //锁对象
    public static Object lock=new Object();
}

线程的运行

package com.qcby.MyThread03;

public class ThreadDemo {

    public static void main(String[] args) {
        Cook c=new Cook();
        Foodie f=new Foodie();

        c.setName("厨师");
        f.setName("吃货");

        c.start();
        f.start();
    }
}

等待唤醒机制第二种实现方式:阻塞队列

注意 put() take()方法的底层实现 自动实现锁的功能了

package com.qcby.MyThread04;

import java.util.concurrent.ArrayBlockingQueue;

public class Cook extends  Thread{

    ArrayBlockingQueue<String> queue;

    public Cook(ArrayBlockingQueue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
       while(true){
           try {
               queue.put("面条");
               System.out.println("厨师放了一碗面条");
           } catch (InterruptedException e) {
               e.printStackTrace();
           }

       }
    }
}

package com.qcby.MyThread04;

import java.util.concurrent.ArrayBlockingQueue;

public class Foodie extends Thread{
    ArrayBlockingQueue<String> queue;

    public Foodie(ArrayBlockingQueue<String> queue) {
        this.queue = queue;
    }
    @Override
    public void run() {
       while(true){
           try {
               String food=queue.take();
               System.out.println("吃货拿走了"+food);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
    }
}

线程实现代码

package com.qcby.MyThread04;

import java.util.concurrent.ArrayBlockingQueue;

public class ThreadDemo {



    public static void main(String[] args) {
        ArrayBlockingQueue<String> queue=new ArrayBlockingQueue<>(1);
        Cook c=new Cook(queue);
        Foodie f=new Foodie(queue);
        c.start();
        f.start();

    }



}

线程的状态

线程池

案例

package com.qcby.ThreadPool;

public class MyRunnable implements  Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+"---"+i);
        }
    }
}

package com.qcby.ThreadPool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadDemo {
    public static void main(String[] args) {
        //获取线程池对象
        ExecutorService pool1=Executors.newCachedThreadPool(); //无上限的线程池

        //提交任务
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());

        //销毁线程池
        pool1.shutdown();

    }
}
相关推荐
黑胡子大叔的小屋6 分钟前
基于springboot的海洋知识服务平台的设计与实现
java·spring boot·毕业设计
ThisIsClark8 分钟前
【后端面试总结】深入解析进程和线程的区别
java·jvm·面试
唐 城9 分钟前
curl 放弃对 Hyper Rust HTTP 后端的支持
开发语言·http·rust
雷神乐乐1 小时前
Spring学习(一)——Sping-XML
java·学习·spring
小林coding2 小时前
阿里云 Java 后端一面,什么难度?
java·后端·mysql·spring·阿里云
V+zmm101342 小时前
基于小程序宿舍报修系统的设计与实现ssm+论文源码调试讲解
java·小程序·毕业设计·mvc·ssm
码银2 小时前
【python】银行客户流失预测预处理部分,独热编码·标签编码·数据离散化处理·数据筛选·数据分割
开发语言·python
从善若水2 小时前
【2024】Merry Christmas!一起用Rust绘制一颗圣诞树吧
开发语言·后端·rust
文大。2 小时前
2024年广西职工职业技能大赛-Spring
java·spring·网络安全
一只小小翠2 小时前
EasyExcel 模板+公式填充
java·easyexcel