Java多线程

java多线程(Thread)

并发与并行

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

并行:在同一时刻,有多个指令在多个cpu上同时运行

多线程的实现方式

1.继承Thread类的方式进行实现

2.实现Runnable接口的方式进行实现

3利用Callable接口和Future接口方式实现

方式一:继承Thread类

1.自己定义一个类继承Thread

2.重写run方法

public class MyThread extends Thread{
​
    @Override
    public void run() {
        //书写线程要执行的代码
        for(int i=0;i<100;i++){
            System.out.println(getName()+"bobo");
        }
    }
}

3.创建子类的对象,并启动线程

public class Test01 {
    public static void main(String[] args) {
​
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
​
        t1.setName("线程1");
        t2.setName("线程2");
​
        t1.start();
        t2.start();
​
    }
}

方式二:实现Runnable接口

1.自己定义一个类实现Runnable接口

2.重写里面的run方法

public class MyThread2 implements Runnable{
    @Override
    public void run() {
        //书写线程要执行的代码
        //获取到当前线程的对象
        Thread t=Thread.currentThread();
        for(int i=0;i<100;i++){
            System.out.println(t.getName()+"bobo");
        }
    }
}

3.创建自己的类的对象

4.创建一个Thread类的对象,并开启线程

public class Test01 {
    public static void main(String[] args) {
​
        //表示多线程要执行的任务
        MyThread2 myThread2 = new MyThread2();
        //创建线程对象
        Thread t1 = new Thread(myThread2);
        Thread t2 = new Thread(myThread2);
        //给线程设置名字
        t1.setName("线程1");
        t2.setName("线程2");
        //开启线程
        t1.start();
        t2.start();
    }
}

方式三:利用Callable接口和Future接口

特点:可以获取到多线程运行的结果

1.创建一个自己类来实现Callable接口

2.重写call(是有返回值的,表示多线程运行的结果)

import java.util.concurrent.Callable;
​
public class MyThread3 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        //求1-100之间的和
        int sum=0;
        for(int i=1;i<=100;i++){
            sum=+sum;
        }
        return sum;
    }
}

3.创建自己类的对象(表示多线程要执行的任务)

4.创建FutureTask的对象(作用管理多线程运行的结果)

5.创建Threda类的对象,并启动(表示线程)

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
​
public class Test01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
​
        //表示多线程要执行的任务
        MyThread3 myThread3 = new MyThread3();
        //创建FutureTask对象(作用管理多线程运行的结果)
        FutureTask<Integer> ft = new FutureTask<>(myThread3);
        //创建线程的对象
        Thread t1 = new Thread(ft);
        //启动线程
        t1.start();
        //获取多线程运行的结果
        Integer rs = ft.get();
        System.out.println(rs);
    }
}
​

多线程三种实现方式的对比

优点缺点
继承Thread类编程比较简单,可以直接使用Thread类中的方法可以扩展性较差,不能再继承其他类
实现Runnable接口扩展性强实现该接口的同时还可以继承其他的类编程相对复杂,不能直接使用Thread类中的方法
实现Callable接口扩展性强实现该接口的同时还可以继承其他的类编程相对复杂,不能直接使用Thread类中的方法

常见的成员方法

方法名称说明
String getName()返回此线程的名称
void setName(String name)设置线程的名称(构造方法也可以设置名称)
static Thread currentThread获取当前线程的对象
static void sleep(long time)让线程休眠指定的时间,单位为毫秒
setPriority(int newPriority)设置线程的优先级
final int getPriority()获取线程的优先级
final void setDaemon(boolean on)设置为守护线程
public static void yield()出让线程/礼让线程
public static void join()插入线程/插队线程

线程的生命周期

线程的安全的问题

同步代码块

把操作共享数据的代码锁起来

格式:

synchronized(锁){

操作共享数据的代码

}

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

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

锁对象一般用当前类的字节码文件对象,例如上图使用MyThread.class

同步方法

就是把synchronized关键字加到方法上

格式:

修饰符 synchronized 返回值类型 方法名 (方法参数){……}

特点1:同步方法是锁住方法里面所有的代码

特点2:锁对象不能自己指定(非静态:this,静态:当前类的字节码文件对象)

死锁

避免死锁错误

线程A和线程B,线程A的a锁和线程B的b锁,a锁和b锁相互等待形成死锁

不要嵌套锁

生产者与消费者(等待唤醒机制)

生产者消费者模式是一个十分经典的多线程协作的模式

两个线程,生产者(生产数据),消费者(消费数据)

情况1:(消费者等待)

情况2:(生产者等待)

常见方法

方法名称说明
void wait()当前线程等待,直到被其他线程唤醒
void notify()随机唤醒单个线程
void notifyAll()唤醒所有线程

缓存区代码块

public class Cache {
    //缓存区
    //控制生产者和消费者的操作
​
    //缓存数据0:表示有没有数据,1表示有数据
    public static int state=0;
​
    //总数据大小
    public static int number=10;
​
    //创建锁对象
    public static Object lock=new Object();
}
​

生产者代码块

public class Producer extends Thread{
    @Override
    public void run() {
        while (true){
            synchronized (Cache.lock){
                //总数据为0时停止
                if(Cache.number==0){
                    break;
                }
                else {
                    //判断是否有数据
                    if (Cache.state==1) {
                        //有数据,就等待
                        try {
                            Cache.lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
​
                    }
                    else{
                        //如果没有数据就生产数据
                        System.out.println("生产者生产数据");
                        //修改状态
                        Cache.state=1;
                        //唤醒消费者消费
                        Cache.lock.notifyAll();
                    }
                }
            }
        }
    }
}

消费者代码块

public class Consumer extends Thread{
    @Override
    public void run() {
        while (true){
            synchronized (Cache.lock){
                //总数据为0时停止
                if(Cache.number==0){
                    break;
                }
                else {
                    //判断缓冲区是否有数据
                    if(Cache.state==0){
                        //没有就等待
                        try {
                            //当前线程与锁进行绑定
                            Cache.lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    else {
                        //有数据就消费
                        Cache.number--;
                        System.out.println("消费者消费数据,还能消费"+Cache.number+"次");
                        //唤醒生产者,继续生产
                        Cache.lock.notifyAll();
                        //修改状态
                        Cache.state=0;
                    }



                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值