多线程

在这里插入图片描述
在这里插入图片描述

第一种方式开辟线程

package com.qianfeng.thread;

public class ThreadCreate {

    public static void main(String[] args) {
        // 线程实例化
        // 1.继承Thread类, 做一个线程子类(自定义线程类)
        MyThread myThread = new MyThread();
        
        // 注意
        // 需要调用start方法, 使线程启动
        // start方法开启一个新的线程,来执行run中的逻辑
        // 如果直接调用run方法,则线程mt不会进入就绪状态
        myThread.start();

        System.out.println("主线程中逻辑执行结束了");
    }

}

/**
 *  这是自定义的线程类
 */
class MyThread extends Thread{

    /**
     *  需要重写run方法
     *  将需要并发执行的任务写到run方法中
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++){
            System.out.println("子线程的逻辑:" + i);
        }
    }
}

在这里插入图片描述
如果是串行的,主线程一定最后打印

第二种方式

package com.qianfeng.thread;

public class ThreadCreate {

    public static void main(String[] args) {
        // 线程实例化
        // 1.继承Thread类, 做一个线程子类(自定义线程类)
        MyThread myThread = new MyThread();

        // 注意
        // 需要调用start方法, 使线程启动
        // start方法开启一个新的线程,来执行run中的逻辑
        // 如果直接调用run方法,则线程mt不会进入就绪状态
        myThread.start();

        // 2.通过Runnable接口

        Runnable runnable = new Runnable() {
            public void run() {
                for (int i = 0; i < 10; i++){
                    System.out.println("线程2的逻辑:" + i);
                }
            }
        };
        
        Thread thread = new Thread(runnable);
        thread.start();

        System.out.println("主线程中逻辑执行结束了");
    }

}

/**
 *  这是自定义的线程类
 */
class MyThread extends Thread{

    /**
     *  需要重写run方法
     *  将需要并发执行的任务写到run方法中
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++){
            System.out.println("子线程的逻辑:" + i);
        }
    }
}

在这里插入图片描述

线程的命名

package com.qianfeng.thread;

public class ThreadMethod {

    public static void main(String[] args) {
        // 线程的命名
        // 1.实例化一个线程对象
//        Thread thread = new Thread();
//        thread.setName("custom");

        // 2.实例化一个线程对象的同时,通过构造方法对线程进行命名
        // Thread(Runnable r, String name)
//        Thread thread = new Thread(() -> {}, "custome");

        // 3.使用自定义的线程类,在实例化线程对象的同时,进行名称的赋值
        // 需要给线程类添加对应的构造方法
        MyThread2 thread = new MyThread2("custom");

        System.out.println(thread.getName());
    }
}

class MyThread2 extends Thread{

    public MyThread2() {
    }

    public MyThread2(String name){
//        super(name);
        this.setName(name);
    }

}

线程休眠

package com.qianfeng.thread;

public class ThreadMethod {

    public static void main(String[] args) {
        threadSleep();
    }

    private static void threadSleep() {
        MyThread2 myThread2 = new MyThread2();
        myThread2.start();
    }
}

class MyThread2 extends Thread{

    @Override
    public void run() {
        for (int i = 0; i < 10; i++){
            System.out.println(i);
            // 线程休眠
            // 1.参数:毫秒为单位的时间差
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

每一秒打印一个数

线程的优先级

package com.qianfeng.thread;

public class ThreadMethod {

    public static void main(String[] args) {
        threadPriority();
    }

    private static void threadPriority() {
        // 设置线程的优先级,只是修改这个线程可以去抢到cpu时间片的概率
        // 并不是优先级高的线程一定能签到cpu的时间片
        // 优先级的设置,是一个整数[0,10]的整数,默认为5
//        Runnable runnable = new Runnable() {
//            @Override
//            public void run() {
//                for (int i = 0; i < 100; i++){
//                    System.out.println(Thread.currentThread().getName() + ":" + i);
//                }
//            }
//        }
        Runnable runnable = () -> {
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        };

        Thread t1 = new Thread(runnable, "Thread-1");
        Thread t2 = new Thread(runnable, "Thread-2");

        // 设置优先级必须要放到这个线程开始执行(start)之前
        t1.setPriority(10);
        t2.setPriority(1);

        t1.start();
        t2.start();
    }
}

class MyThread2 extends Thread{

    @Override
    public void run() {
        for (int i = 0; i < 10; i++){
            System.out.println(i);
            // 线程休眠
            // 1.参数:毫秒为单位的时间差
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述

线程的礼让

package com.qianfeng.thread;

public class ThreadMethod {

    public static void main(String[] args) {
        threadYield();
    }

    private static void threadPriority() {
        // 设置线程的优先级,只是修改这个线程可以去抢到cpu时间片的概率
        // 并不是优先级高的线程一定能签到cpu的时间片
        // 优先级的设置,是一个整数[0,10]的整数,默认为5
//        Runnable runnable = new Runnable() {
//            @Override
//            public void run() {
//                for (int i = 0; i < 100; i++){
//                    System.out.println(Thread.currentThread().getName() + ":" + i);
//                }
//            }
//        }
        Runnable runnable = () -> {
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        };

        Thread t1 = new Thread(runnable, "Thread-1");
        Thread t2 = new Thread(runnable, "Thread-2");

        // 设置优先级必须要放到这个线程开始执行(start)之前
        t1.setPriority(10);
        t2.setPriority(1);

        t1.start();
        t2.start();
    }

    /**
     *  线程的礼让
     */
    private static void threadYield() {
        // 线程礼让,指的是当前的运行状态的线程释放自己的cpu资源,由运行状态,回到就绪状态,并重新开始争抢cpu资源
        Runnable r = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + ";" + i);
                    if (i == 3) {
                        Thread.yield();
                    }
                }
            }
        };

        Thread t1 = new Thread(r,"thread-1");
        Thread t2 = new Thread(r,"thread-2");

        t1.start();
        t2.start();

    }
}

class MyThread2 extends Thread{

    @Override
    public void run() {
        for (int i = 0; i < 10; i++){
            System.out.println(i);
            // 线程休眠
            // 1.参数:毫秒为单位的时间差
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述

临界资源问题展示

进程资源不共享,但是线程资源共享

package com.qianfeng.sourceconflict;

public class SourceConflict {

    // 演示临界资源问题
    // 某个景点由4个售票员同时在售票
    public static void main(String[] args) {
        // 实例化4个售票员,用4个线程模拟4个售票员
        Runnable r = () -> {
            while (TicketCenter.restCount >0) {
                System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter.restCount + "张");
            }
        };

        // 用四个线程模拟4个售票员
        Thread t1 = new Thread(r,"thread - 1");
        Thread t2 = new Thread(r,"thread - 2");
        Thread t3 = new Thread(r,"thread - 3");
        Thread t4 = new Thread(r,"thread - 4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }
}

class TicketCenter {
    // 描述剩余的票的数量
    public static int restCount = 100;
}

在这里插入图片描述

解决临界资源问题

同步代码段

package com.qianfeng.sourceconflict;

public class SynchronizedDemo {

    public static void main(String[] args) {
        // 实例化4个售票员,用4个线程模拟4个售票员
        Runnable r = () -> {
            while (TicketCenter.restCount >0) {
                // 对象锁: ""
                // 类锁:
                // 需要保证一点,多个线程看到的锁,需要时同一把锁!!!
                synchronized (SynchronizedDemo.class){
                    if (TicketCenter2.restCount <= 0) {
                        return;
                    }
                    System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter2.restCount + "张");
                }
            }
        };

        // 用四个线程模拟4个售票员
        Thread t1 = new Thread(r,"thread - 1");
        Thread t2 = new Thread(r,"thread - 2");
        Thread t3 = new Thread(r,"thread - 3");
        Thread t4 = new Thread(r,"thread - 4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }
}

class TicketCenter2{
    // 描述剩余的票的数量
    public static int restCount = 100;
}

在这里插入图片描述

同步方法

package com.qianfeng.sourceconflict;

public class SynchronizedFunction {

    public static void main(String[] args) {
        // 实例化4个售票员,用4个线程模拟4个售票员
        Runnable r = () -> {
            while (TicketCenter.restCount >0) {
                // 对象锁: ""
                // 类锁:
                // 需要保证一点,多个线程看到的锁,需要时同一把锁!!!
                soldTicket();
            }
        };

        // 用四个线程模拟4个售票员
        Thread t1 = new Thread(r,"thread - 1");
        Thread t2 = new Thread(r,"thread - 2");
        Thread t3 = new Thread(r,"thread - 3");
        Thread t4 = new Thread(r,"thread - 4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }


    /**
     *  同步方法
     *  静态方法: 同步锁就是 类锁 当前类.class
     *  非静态方法: 同步锁 是 this
     */
    private synchronized static void soldTicket() {
        if (TicketCenter.restCount <= 0) {
            return;
        }
        System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter.restCount + "张");
    }
}

在这里插入图片描述

显示锁

package com.qianfeng.sourceconflict;

import java.util.concurrent.locks.ReentrantLock;

public class LockDemo {

    public static void main(String[] args) {

        ReentrantLock lock = new ReentrantLock();

        // 实例化4个售票员,用4个线程模拟4个售票员
        Runnable r = () -> {
            while (TicketCenter2.restCount > 0) {

                // 对临界资源上锁
                lock.lock();

                if (TicketCenter2.restCount <= 0) {
                    return;
                }
                System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter2.restCount + "张");

                // 对临界资源解锁
                lock.unlock();
            }
        };

        // 用四个线程模拟4个售票员
        Thread t1 = new Thread(r, "thread - 1");
        Thread t2 = new Thread(r, "thread - 2");
        Thread t3 = new Thread(r, "thread - 3");
        Thread t4 = new Thread(r, "thread - 4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }

}

在这里插入图片描述

死锁

package com.qianfeng.sourceconflict;

public class DeadLock {

    public static void main(String[] args) {
        // 死锁: 多个线程彼此持有对方所需要的锁对象,而不释放自己的锁
        Runnable runnable1 = () -> {
            synchronized ("A") {
                System.out.println("A线程持有了A锁,等待B锁");

                synchronized ("B") {
                    System.out.println("A线程持有了A锁和B锁");
                }
            }
        };

        Runnable runnable2 = () -> {
            synchronized ("B") {
                System.out.println("B线程持有了B锁,等待A锁");

                synchronized ("A"){
                    System.out.println("B线程持有了A锁和B锁");
                }
            }
        };

        Thread thread1 = new Thread(runnable1);
        Thread thread2 = new Thread(runnable2);

        thread1.start();
        thread2.start();
    }
}

在这里插入图片描述

解决死锁

package com.qianfeng.sourceconflict;

public class DemoLock {

    public static void main(String[] args) {
        // 死锁: 多个线程彼此持有对方所需要的锁对象,而不释放自己的锁

        // wait:等待, 是Object类中的一个方法,当前的线程释放自己的标记,并且让出cpu资源,使得当前的线程进入等待队列中。
        // notify: 通知, 是Object类中的一个方法, 唤醒等待队列中的一个线程,使这个线程进入锁池。
        // notifyAll: 通知, 是Object类中的一个方法,唤醒等待队列中所有的线程,并使这些线程进入锁池。

        Runnable runnable1 = () -> {
            synchronized ("A") {
                System.out.println("A线程持有了A锁,等待B锁");

                try {
                    "A".wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized ("B") {
                    System.out.println("A线程持有了A锁和B锁");
                }
            }
        };

        Runnable runnable2 = () -> {
            synchronized ("B") {
                System.out.println("B线程持有了B锁,等待A锁");

                synchronized ("A"){
                    System.out.println("B线程持有了A锁和B锁");

                    "A".notifyAll();
                }
            }
        };

        Thread thread1 = new Thread(runnable1);
        Thread thread2 = new Thread(runnable2);

        thread1.start();
        thread2.start();
    }

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值