多线程
(1)

多线程

自定义线程类继承Thread类

重写run方法,编写线程执行体

创建线程对象,调用start()方法启动线程。

package com.wang.threads;

/**
 * @author valive
 * @create 2021-04-14 15:56
 **/
public class TestThread1 extends Thread {
    @Override
    public void run(){
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("你好"+i);
        }
    }

    public static void main(String[] args) {
        //main线程,主线程
        TestThread1 testThread1 =new TestThread1();
        testThread1.run();
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看电视"+i);
        }
    }
}

run方法先执行run(),完了再走主路径。只有主线程一条执行路径

start方法有多条执行路径,主线程和子线程同时执行。

线程开启不一定立即就执行,看CPU调度。

继承Thread类

  • 子类继承Thread类具备多线程能力
  • 启动线程:子类对象.start()
  • 但是不建议使用这种:避免oop单继承局限性

实现Runnable接口

  • 实现接口Runnable具有多线程能力
  • 启动线程:传入目标对象+Thread对象.start()
  • 推荐使用,避免单继承局限性,灵活方便,方便同一个对象被多个线程使用
package com.wang.threads;

/**
 * @author valive
 * @create 2021-04-14 19:43
 **/
public class TestThread2  implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 200; i++) {
            System.out.println("你好"+i);
        }
    }

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

        new Thread(testThread2).start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("世界"+i);
        }
    }
}

模拟龟兔赛跑

package com.wang.threads;

/**
 * @author valive
 * @create 2021-04-14 20:04
 **/
public class Race implements Runnable{
    //胜利者
    private static String winner;
    
    @Override
    public void run(){
        for (int i = 0; i <= 100; i++) {
            //模拟兔子休息
            if (Thread.currentThread().getName().equals("兔子")&&i%10==0){
                try {
                    Thread.sleep(5);
                }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;
        }{
            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=new Race();

        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();


    }
    
}

静态代理模式

  • 真实对象和代理对象都要实现同一个接口
  • 代理对象要代理真实角色
  • 好处是代理对象可以做很多真实对象做不来的,真实对象可以专注做自己的事情
package com.wang.threads;

/**
 * @author valive
 * @create 2021-04-15 14:54
 **/
public class StaticProxy {
    public static void main(String[] args) {

        new Thread(()-> System.out.println("我爱你")).start();
        You you =new You();

        WeddingCompany weddingCompany =new WeddingCompany(new You());
        weddingCompany.HappyMarry();
    }
}

interface Marry{
    void HappyMarry();
}
//真实角色,你去结婚
class You implements Marry{
    @Override
    public void HappyMarry(){
        System.out.println("结婚");
    }
}
//代理角色,帮助你结婚
class WeddingCompany implements Marry{
    //代理谁-->真实目标角色
    private Marry target;

    public WeddingCompany(Marry target){
        this.target=target;
    }
    @Override
    public void HappyMarry(){
        before();
        this.target.HappyMarry();//真实对象调用的结婚
        after();
    }
    private void after(){
        System.out.println("结婚后睡觉");

    }
    private  void  before(){
        System.out.println("结婚之前布置现场");

    }
}

Lambda表达式

用处是避免匿名内部类定义过多,能使代码更加简洁;其实质属于函数式编程的概念。

任何接口,如果只包含唯一一个抽象方法,那么他就是函数式接口

package com.wang.threads;

/**
 * 推导lamda表达式
 */

/**
 * @author valive
 * @create 2021-04-15 15:46
 **/
public class TestLambada1 {
    //静态内部类
    static class Like2 implements ILikce{
        @Override
        public void lambda(){
            System.out.println("lambda2");
        }
    }
    public static void main(String[] args) {
        ILikce like =new Like();
        like.lambda();

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

        //局部内部类
        class Like3 implements ILikce {
            @Override
            public void lambda() {
                System.out.println("lambda3");
            }
        }
        like =new Like3();
        like.lambda();

        //匿名内部类,没有类名,必须借助接口或者父类
        like =new ILikce(){
            @Override
            public void lambda() {
                System.out.println("lambda4");
            }
        };
        like.lambda();

        //用lambda简化
        like = ()-> {
            System.out.println("lambda5");
        };
        like.lambda();

        //lambda表达式,只能有有一行代码的情况下才能简化为一行,多行只能简化到代码块。
        like=()->System.out.println("lambda6");
        like.lambda();

    }
}
//定义一个函数式接口
interface ILikce{
    void lambda();
}
//实现类
class Like implements ILikce{
    @Override
    public void lambda(){
        System.out.println("lambda");
    }
}

sleep实现线程的休眠

package com.wang.sleep;

/**
 * @author valive
 * @create 2021-04-17 13:51
 **/
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;
            }
        }
    }
}

礼让yield

package com.wang.sleep;

import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * @author valive
 * @create 2021-04-17 13:55
 **/
//礼让不一定成功,看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()+"end");
    }
}

join,线程强制执行

合并线程,待该线程执行完成了,再执行其他的线程,其他线程阻塞;尽量不使用。

package com.wang.sleep;

/**
 * @author valive
 * @create 2021-04-17 14:05
 **/
public class TestJoin implements Runnable {


    @Override
    public void run() {
        for (int i = 0; i < 100; 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 < 400; i++) {
            if (i==200){
                thread.join();
            }
            System.out.println("main"+i);
        }
    }
}

守护线程

线程分为用户线程和守护线程

虚拟机必须确保用户线程执行完毕

虚拟机不用等待守护线程执行完毕。

package com.wang.sleep;

/**
 * @author valive
 * @create 2021-04-17 14:48
 **/
public class TestDaemon {
    public static void main(String[] args) {
        God god=new God();
        You you=new You();

        Thread thread=new Thread(god);
        thread.setDaemon(true);//默认是false,表示是用户线程,正常的线程都是用户线程

        thread.start();//启动神守护线程
        new Thread(you).start();
    }

}
    class God implements Runnable{

        @Override
        public void run() {
            while (true){
                System.out.println("神保护着你");
            }
        }
    }
    class You implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 36500; i++) {
                System.out.println("天天开心");

            }
            System.out.println("离开了世界");
        }
    }

同步方法和同步块

可以通过private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提出一套机制,这套机制就是synchronized关键字,包含synchronized方法和synchronize块。

方法执行就独占一个锁,直到方法返回释放,后面被阻塞的线程才能获得这个锁,继续执行。

缺点是 :如果将一个大的方法申明为synchronized会影响效率。

同步块:synchronized(Obj){}

Obj为同步监视器,可以为任何对象,但是推荐使用共享资源作为同步监视器。

同步方法无需指定同步监视器,因为同步方法的同步监视器就是this ,就是这个对象本身。

避免死锁

package com.wang.lock;

/**
 * @author valive
 * @create 2021-04-17 16:38
 **/
//多个线程互相拥有对方需要的资源,然后形成了僵持
public class DeafLock {
    public static void main(String[] args) {
        Mackup g1=new Mackup(0,"bluer");
        Mackup g2=new Mackup(0,"reds");

        g1.start();
        g2.start();
    }

}
class Lipstick{

}

class Mirror{

}
class Mackup extends Thread {
    //用static保证只有一份资源
    static Lipstick lipstick = new Lipstick();
    static Mirror mirror = new Mirror();

    int choice;
    String girlName;

    Mackup(int choice, String girlName) {
        this.choice = choice;
        this.girlName = girlName;
    }

    @Override
    public void run() {
        //化妆
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void makeup() throws InterruptedException {
        if (choice == 0) {
            synchronized (lipstick) {//获得口红的锁
                System.out.println(this.girlName + "获得口红锁");
                Thread.sleep(1000);
            }
                synchronized (mirror) {//一秒后获得镜子的锁
                    System.out.println(this.girlName + "获得镜子的锁");
                }
            }
        else{
            synchronized (mirror) {//一秒后获得镜子的锁
                System.out.println(this.girlName + "获得镜子的锁");
                Thread.sleep(2000);
            }
                synchronized (lipstick) {//获得口红的锁
                    System.out.println(this.girlName + "获得口红锁");}
            }

        }
    }
本文为作者valive发布,未经允许禁止转载!
上一篇 下一篇
评论
评论已关闭 >_<

评论已关闭