Java总结:多线程

多线程

进程与线程

    打个QQ,开了一个进程,再开个QQ,有开了一个进程,开了迅雷,又开了一个进程。

    在QQ里头可以 传输 文字,语言,小广告,那么可以理解为传输文字,语言,小广告就是开了一个线程,线程可以理解为 “任务”。

    一个进程可以管理多个线程,进程是爹妈,管理众多线程儿子。

    进行本身不执行,只为线程的执行提供运行的环境,申请内容空间的。

什么是多线程

    一个进程里面同时执行多个任务(线程、执行路径)。  

    一个进程里头只是包含一个线程。

    开启多线程,是为了 “同时”执行多个任务,

    也就是 “同时”执行多部分代码。

多线程弊端

    弊端:线程切换耗费额外的资源,切换本身也是耗时间的。

    好处:解决了多部分代码 同时 运行的问题

    案例:验证JVM的启动


class User extends Object{

    protected void finalize() throws Throwable {
        System.out.println("我要被回收了");
    }
}
public class Demo01 {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("hello Thread--------");
        for(int i = 0;i < 10;i++){
            new User();
        }
        System.gc();//手动触发垃圾回收
        Thread.sleep(1);
        System.out.println("hello Thread========");
    }
}

    通过多次运行,发现输出结果的顺序有随机性,有多个“人”在跑

总结:

(1)JVM启动至少2个线程,一个主(main)线程,垃圾回收线程。

(2)线程之间的执行顺序是随机的,也就是那个线程占有CPU谁就执行。

怎么创建线程

方式一:继承Thread

    代码如下

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"老王,被打死了");
        //Thread.currentThread().getName()获取当前线程的名称
    }
}
public class Demo02 {
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        myThread.start();//启动一个线程
        Thread.sleep(3);//线程休眠
        System.out.println(Thread.currentThread().getName()+"老王复活了");
    }
}

实现步骤

(1)创建一个类,继承Thread,

(2)子类重写run方法,原因:创建线程目的是为了跑任务,任务代码写在run方法里头

(3)创建子类对象,

(4)开启线程。调用start方法

Thread常用方法和属性

    currentThread:获取当前线程

    name:线程的名称

方式二:Runnable接口

    代码实现


class MyRunnable implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i <10 ; i++) {
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"转世"+i);
        }
    }
}
public class Demo03 {
    public static void main(String[] args) {
        MyRunnable myRunnable1 = new MyRunnable();
        MyRunnable myRunnable2 = new MyRunnable();
        Thread thread1 = new Thread(myRunnable1, "小李");
        Thread thread2 = new Thread(myRunnable2, "老王");
        thread1.start();
        thread2.start();
        System.out.println(Thread.currentThread().getName()+"完了");
    }
}

实现步骤

(1)创建一个类,时间runnable接口

(2)重写run方法,并且在run方法里面,写清楚你要干的活的。

(3)创建一个线程Thread(myRunnable,”线程的名字”)

(4)开启线程

总结     

    java是单继承,如果使用方式一创建线程,要求该类不能继承与其他父类,

    往往我们使用 接口 方式扩展。

    将线程任务 与 线程进行分离,对任务进行单独的封装。

    一般情况下使用第二种方式

线程的调度

    挂号之后病人处于新建状态,

    排队候诊就是就绪状态;

    当轮到医生给你看病的时候,就是运行状态,

    当医生给你开验血单,在等待化验结果的时候,医生给其他病人看病,

    在此之间处于阻塞状态,

    当你拿到化验单医生再次为你服务,恢复为就绪状态。

线程状态:

   新建状态

   就绪状态

   运行状态

   阻塞状态

线程优先级

   可以给线程设置优先级,优先级高的先跑,但是不意味着先跑完。


class Tach implements Runnable{

    private String name;
    public Tach(String name){
        this.name = name;
    }
    @Override
    public void run() {
        for (int i = 0 ; i< 10;i++){
            System.out.println("to"+name+i);
            Thread.yield();//让步,只会让优先级比自己高得线程

        }
        System.out.println("bye....");
    }
}
public class Demo04 {
    public static void main(String[] args) {
        Tach zx = new Tach("测试员");
        Tach ls = new Tach("项目经理");
        Thread t1 = new Thread(zx);
        Thread t2 = new Thread(ls);
        t1.setPriority(Thread.MAX_PRIORITY);//设置优先级
        t2.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        t2.start();
    }
}

线程休眠sleep

    设置休眠的时间,时间到了接着运行。阻塞线程。

    Thread.sleep( 100 );

线程让步yield

    yield()方法可以让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程从运行状态转入就绪状态。

    只会给比自己 >=自己优先级的线程。

线程插队join


public class Demo05 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        });
        thread.start();
        for(int i = 0;i < 5 ;i++){
            System.out.println(Thread.currentThread().getName());
            if(i==3){
                thread.join();
            }
        }
    }
}

线程安全(线程同步)

    一个任务的代码实现超过2行,就有可能出现线程安全问题。

    通过同步代码块的方式,保证 任务 的代码 只能一个线程跑,

    当一个线程在运行同步代码块的时候,其他线程只能等待。

Synchronized:

    保证一个方法或者一个代码块在同一时间只被一个线程访问

线程的死锁

    2个人吃饭,只有2个筷子,每个个右手边各一只,

    吃饭:A拿起右手边,等待B把左手边那个筷子放下,

           B 等待A

    原因:资源的竞争,

线程的协作

    生产者和消费者

    PV操作

    wait:是当前线程进入阻塞状态,相当于P 操作  +

    notify:唤醒此同步锁上阻塞的第一个线程,相当于V操作 -

    notifyALL: 唤醒此同步锁上阻塞的所有线程

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无名一小卒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值