• 多线程基础


    线程创建

    继承Thread类

    public class TestThread1 extends Thread{
        @Override
        public void run() {
            // run 方法线程体
            System.out.println("我在看视频");
        }
        public static void main(String[] args) {
            // main 主线程体
            // 创建一个线程对象
            TestThread1 testThread1 = new TestThread1();
            // 调用start()方法开启线程
            testThread1.start();
        }
    }

    实现Runnable接口

    public class TestThread2 implements Runnable {
        @Override
        public void run() {
            System.out.println("我在学习");
        }
        public static void main(String[] args) {
            TestThread2 testThread2 = new TestThread2();
    
            // 开启子线程 (这里采用代理模式)
            new Thread(testThread2).start();
        }
    }

    实现Callable接口(了解)

    public class TestThread3 implements Callable<Integer> {
        // 这里需要返回类型
        @Override
        public Integer call() throws Exception {
            System.out.println("法外狂徒张三在作案");
            return 100;
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            FutureTask<Integer> futureTask = new FutureTask<Integer>(new TestThread3());
            new Thread(futureTask).start();
            Integer integer = futureTask.get(); // 这里获取返回值
            System.out.println(integer);
        }
    }

    线程状态

    查看线程的状态通过getState()方法。

    线程休眠

    Thread.sleep(1000); // 单位是毫秒
    • sleep指定当前线程阻塞的毫秒数
    • sleep时间到达后线程进入就绪状态
    • 每一个对象都有一个锁,sleep不会释放锁

     

    线程礼让

    Thread.yield();  // 礼让
    • 礼让线程,让当前正在执行的线程暂停,但不阻塞
    • 将线程从运行状态转为就绪状态
    • 礼让是让cpu重新调度,所以礼让不一定成功!

    线程插入

    public static void main(String[] args) throws InterruptedException {
            // 自定义线程
            Thread t = new Thread(()-> {
                for (int i = 0; i < 10; i++) {
                    System.out.println("我来插入执行");
                }
            });
    
            // 主线程
            for (int i = 0; i < 20; i++) {
                if (i == 10) {
                    t.join(); // 强制插入t线程,待t线程执行完,再继续执行main线程
                }
                System.out.println("我是主线程");
            }
        }

    线程优先级

    • 线程调度器按照优先级决定应该调度哪个线程来执行
    • 线程的优先级用数字表示,范围从1~10
    • getPriority() 获取优先级
    • setPriority(int xx) 设置优先级
    • 注意:若设置优先级,一定先设置优先级,后启动

    守护线程

    • 线程分为用户线程和守护线程
    • 虚拟机必须确保用户线程执行完毕
    • 虚拟机不用等待守护线程执行完毕
    • 通过setDaemon(true)来设置该线程为守护线程

    锁问题

    初步了解多线程在并发问题中,采取的简单措施。

    • synchronized 关键字,锁的是this,用于同步方法,或者代码块
    • 可重入锁Lock,ReentrantLock类实现了Lock,它拥有与synchronized 相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显示加锁,释放锁。

    生产消费者模式

    生产消费者模式问题可以有两种解决方法:管道法(用缓冲区)、信号灯法(标识变量)

    示例:缓冲区方式

    public class TestPC {
    
        public static void main(String[] args) {
            SynContainer container = new SynContainer();
            new Productor(container).start();
            new Consumer(container).start();
        }
    }
    
    // 生产者 线程
    class Productor extends Thread{
        SynContainer container;
        public Productor(SynContainer container) {
            this.container = container;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                try {
                    container.product(new Chicken(i));
                    System.out.println("生产-->" + i/10 + "-" + i%10 + "只鸡");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    // 消费者 线程
    class Consumer extends Thread {
        SynContainer container;
        public Consumer(SynContainer container) {
            this.container = container;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                try {
                    Chicken chicken = container.pop();
                    System.out.println("消费了-->" + chicken.getId()/10 + "-" + chicken.getId()%10 + "只鸡");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    // 产品
    class Chicken {
        int id; // 编号
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public Chicken(int id) {
            this.id = id;
        }
    }
    
    class SynContainer {
        // 声明缓冲区的数量
        Chicken[] chickens = new Chicken[10];
    
        // 存在的数量
        int count = 0;
    
        // 生产一只鸡
        public synchronized void product(Chicken chicken) throws InterruptedException {
            while (count >= 9) {
                this.wait();
            }
            chickens[count++] = chicken;
            this.notifyAll(); // 唤醒消费进程
        }
    
        // 消费鸡
        public synchronized Chicken pop() throws InterruptedException {
            while (count <= 0) {
                this.wait();
            }
            count--;
            this.notifyAll(); // 唤醒生产者
            return chickens[count];
        }
    }
  • 相关阅读:
    介绍Shiro Annotation及Shiro标签的用法
    SpringMVC+Apache Shiro+JPA(hibernate)案例教学(四)基于Shiro验证用户权限,且给用户授权
    SpringMVC+Apache Shiro+JPA(hibernate)案例教学(一)整合配置
    Spring MVC之@RequestMapping 详解
    vimrc
    sk_buff深度解析
    ieee80211ax简介
    新基地
    dos格式迭代转为unix
    ath10k MAC地址
  • 原文地址:https://www.cnblogs.com/liuyu666/p/14043357.html
Copyright © 2020-2023  润新知