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();

    }
}
相关推荐
工一木子18 分钟前
【Java项目脚手架系列】第七篇:Spring Boot + Redis项目脚手架
java·spring boot·redis
哞哞不熬夜30 分钟前
JavaEE--初识网络
java·网络·java-ee
等等54342 分钟前
Java EE初阶——wait 和 notify
java·开发语言
低代码布道师1 小时前
第五部分:第一节 - Node.js 简介与环境:让 JavaScript 走进厨房
开发语言·javascript·node.js
API小爬虫1 小时前
淘宝按图搜索商品(拍立淘)Java 爬虫实战指南
java·爬虫·图搜索算法
盛夏绽放1 小时前
Python字符串常用方法详解
开发语言·python·c#
lyrhhhhhhhh1 小时前
Spring 框架 JDBC 模板技术详解
java·数据库·spring
亚林瓜子2 小时前
AWS Elastic Beanstalk控制台部署Spring极简工程
java·spring·云计算·aws·eb
2401_cf2 小时前
如何创建maven项目
java·maven·intellij-idea
好吃的肘子2 小时前
Elasticsearch架构原理
开发语言·算法·elasticsearch·架构·jenkins