多线程笔记

目录

1.概念:

2.线程状态:

3.线程方法:

4.实现:

4.1 继承Thread类

运行结果:

4.2 实现Runnable接口

5.线程方法示例

5.1 线程停止

 示例代码

5.2 sleep方法

示例代码

5.3 yield方法

示例代码

5.4 Join方法

示例代码 

6.线程安全问题

6.1 抢票

7.巩固练习:

7.1 龟兔赛跑

8.Lambda表达式

8.1 lambda发展历程


1.概念:

  • 程序:是指令和数据的集合,本身没有任何运行的含义,是一个静态的概念
  • 进程:是程序的一次执行过程,它是一个动态的概念,是资源分配的单位
  • 线程:通常在一个进程中包含若干个线程,一个进程中至少有一个线程,不然没有意义。先线程是CPU调度和执行的单位

2.线程状态:

3.线程方法:

常用方法
方法说明
setPriority(int newPriority)             更改线程的优先级
static void sleep(long millis)    在指定的毫秒数内让线程休眠
void join()   等待该线程终止
static void yield()暂停当前正在执行的线程对象,并执行其他线程
void interrupt()中断线程(不建议使用)
boolean isAlive()测试线程是否处于活动状态

4.实现:

4.1 继承Thread类

public class TestThread1 extends Thread {
    @Override
    public void run() {
        // 重写run()方法,实现线程的执行操作
        for (int i = 0; i <20; i++) {
            System.out.println("我在看代码");
        }
    }

    public static void main(String[] args) {
        TestThread1 testThread1=new TestThread1();

        // 创建线程对象
        testThread1.start();

        // 主线程
        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程");
        }
    }
}

运行结果:

总结:1.主线程和子线程同时执行

           2.线程开启不一定立刻执行由cpu调度安排

4.2 实现Runnable接口

//实现Runnable接口
public class TestThread2 implements Runnable {

    @Override
    public void run() {
        // 重写run()方法,实现线程的执行操作
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码");
        }
    }

    public static void main(String[] args) {
        TestThread1 testThread2 = new TestThread1();

        //创建线程

        new Thread(testThread2).start();
        // 主线程
        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程");
        }
    }
}

总结:推荐使用实现Runnable接口,避免单继承局限性,灵活方便,方便同一个对象被多个线程使用。

5.线程方法示例

5.1 线程停止

  • 建议线程正常停止,不建议死循环
  • 建议使用标志位
  • 不要使用stop或destroy

 示例代码

public class TestStop implements Runnable {
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("run ...Thread" + i++);
        }
    }

    //停止线程
    public void stop() {
        this.flag = false;
    }

    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        //创建线程
        new Thread(testStop).start();
        //循环1000次
        for (int i = 0; i < 1000; i++) {

            //当i等于900时,停止线程
            if (i == 900) {
                testStop.stop();
                System.out.println("线程停止");
            }
        }
    }
}

5.2 sleep方法

  • 指定线程阻塞的毫秒数
  • 存在异常InterruptedException
  • 达到时间后进入就绪状态
  • 模拟网络延时,倒计时等
  • 每一个对象都有一把锁,sleep不会释放锁

示例代码

//模拟倒计时
public class testSleep {
    public static void main(String[] args) {
        try {
            tenDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void tenDown() throws InterruptedException{
        int num=10;
        while(true){
            Thread.sleep(1000);
            System.out.println(num--);
            if (num <= 0) {
                  break;
            }
        }
    }
}

5.3 yield方法

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞
  • 让线程从运行状态转为就绪状态
  • 让CPU重新调度(不一定成功)

示例代码

public class TestYield {
    public static void main(String[] args) {
        MyYield myYield = new MyYield();
        new Thread(myYield, "a").start();
        new Thread(myYield, "b").start();

    }

}

class MyYield implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始执行");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + "线程停止执行");

    }
}

5.4 Join方法

Join合并线程。待此线程执行完成后,再执行其他线程,其他线程阻塞。(可以想象成插队) 

示例代码 

public class TestJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("线程vip"+i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestJoin testJoin=new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();
        for (int i = 0; i < 500; i++) {
            if(i==100){
                thread.join();
            }
            System.out.println("main"+i);

        }
    }
}

6.线程安全问题

6.1 抢票

public class TestThread3 implements Runnable {
    private int tickNum = 10;
    @Override
    public void run() {
        //当tickNum小于等于0时,结束循环
        while (true) {
            if (tickNum <= 0) {
                break;
            }
            try {
                //线程休眠200毫秒
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //输出当前线程名称和tickNum的值
            System.out.println(Thread.currentThread().getName() + "--" + tickNum--);
        }
    }

    public static void main(String[] args) {

        //创建一个TestThread3类的实例
        TestThread3 ticket = new TestThread3();

        //创建线程,并传入参数ticket和"小明"
        new Thread(ticket, "小明").start();

        //创建线程,并传入参数ticket和"老师"
        new Thread(ticket, "老师").start();

        //创建线程,并传入参数ticket和"小红"
        new Thread(ticket, "小红").start();


    }
}

发现问题:多个线程操作统一资源,线程不安全,数据紊乱。

7.巩固练习:

7.1 龟兔赛跑

public class Race implements Runnable {
    private String winner;
    @Override
   public void run() {
        for (int i = 0; i <= 100; i++) {
            //判断当前线程是否为兔子,并且i是否为10的倍数
            if (Thread.currentThread().getName().equals("兔子") && i % 10 == 0) {
                try {
                    //线程休眠1毫秒
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //判断是否游戏结束
            Boolean flag = gameOver(i);
            //如果游戏结束,则跳出循环
            if (flag) {
                break;
            }
            //输出当前线程名和跑了多少步
            System.out.println(Thread.currentThread().getName() + "--->跑了" + i + "步");

        }
    }
    private boolean gameOver(int steps) {
        //检查是否有获胜者
        if (winner != null) {
            return true;
        }
        //检查是否超过100步
        {
            if (steps >= 100) {
                //设置获胜者为当前线程
                winner = Thread.currentThread().getName();
                System.out.println("winner is " + winner);
                return true;
            }
        }
        return false;
    }

   public static void main(String[] args) {
        // 创建一个Race对象
        Race race = new Race();
        // 创建一个新的线程,并将其命名为兔子
        new Thread(race, "兔子").start();
        // 创建一个新的线程,并将其命名为乌龟
        new Thread(race, "乌龟").start();
    }
}

8.Lambda表达式

  • 避免匿名内部类过多
  • 其实质属于函数式编程

函数式编程:

  • 任何接口,如果只包含唯一一个抽象方法,他就是一个函数式接口
  • 对于函数式接口可以使用Lambda表达式创建接口对象

8.1 lambda发展历程

public class TestLambda1 {
    //3.静态内部类
    static class Like2 implements ILike {
        @Override
        public void lambda() {
            System.out.println("I like lambda2");
        }
    }

    public static void main(String[] args) {

        ILike like = new Like();
        like.lambda();

        like = new Like2();
        like.lambda();

        //4.局部内部类
        class Like3 implements ILike {
            @Override
            public void lambda() {
                System.out.println("I like lambda3");
            }
        }
        like = new Like3();
        like.lambda();
        //5.匿名内部类
        like = new ILike() {
            @Override
            public void lambda() {
                System.out.println("I like lambda4");
            }
        };
        like.lambda();
        //6.用lambda简化
        like = () -> {
            System.out.println("I like lambda5");
        };
        like.lambda();

    }
}

//1.定义一个函数式接口
interface ILike {
    void lambda();
}

//2.实现类
class Like implements ILike {

    @Override
    public void lambda() {
        System.out.println("I like lambda");
    }
}

狂神说多线程(力推)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值