07-多线程


多线程

三中创建方式

继承Thread类*

  • 子类继承Thread类具备多线程能力
  • 启动线程:子类对象.start()
  • 避免OOP单继承局限性

实现Runable接口*

  • 实现接口Runable具有多线能力
  • 启动线程:传入目标对象+Thread对象
  • 避免单继承局限性,灵活方便,方便一个对象被多个线程使用

实现Callable接口

Thread

//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程

//总结:注意:线程开启不一定立即执行,由cpu调度执行
public class TestThread01 extends Thread{
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("run");
        }

    }

    public static void main(String[] args) {
        //主方法,主线程
        //创建一个线程对象
        TestThread01 testThread01 = new TestThread01();
        //调用start方法开启线程
        testThread01.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("main");
        }
    }
}
/**
 * 线程同时下载图片
 */
public class TestThread02 extends Thread{
    private URL url;
    private String name;
    public TestThread02(String src,String name)  {
        try {
            this.url = new URL(src);
            this.name = name;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

    }

    /**
     * 下载图片线程执行体
     */
    @Override
    public void run() {
        try {
            HttpsURLConnection httpURLConnection = (HttpsURLConnection) url.openConnection();
            InputStream inputStream = httpURLConnection.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream(name);
            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes))!= -1){
                fileOutputStream.write(bytes,0,len);
            }
            System.out.println("下载了" + name);
            fileOutputStream.close();
            inputStream.close();
            httpURLConnection.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        TestThread02 testThread1 = new TestThread02("https://pic.netbian.com/uploads/allimg/210812/234309-1628782989c289.jpg","天空小姐姐 黑色唯美裙子.jpg");
        TestThread02 testThread2 = new TestThread02("https://pic.netbian.com/uploads/allimg/210920/165135-1632127895c615.jpg","短发女孩 袜子 窗户 云 .jpg");
        TestThread02 testThread3 = new TestThread02("https://pic.netbian.com/uploads/allimg/190824/212516-1566653116f355.jpg","下午 趴在桌子的女孩.jpg");

        testThread1.start();
        testThread2.start();
        testThread3.start();

    }
}

Runable

//创建线程方式2:实现Runable接口,重写run方法,执行线程需要Runable接口的实现,调用start方法
public class TestTHread3 implements Runnable{
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("run");
        }

    }

    public static void main(String[] args) {
        //主方法,主线程
        //创建一个runable接口的实现对象;
        TestTHread3 testTHread3 = new TestTHread3();
        //创建线程对象,通过线程对象来开启我们的线程。代理
        //Thread thread = new Thread(testTHread3);
        //调用start方法开启线程
        //thread.start();
        new Thread(testTHread3).start();



        for (int i = 0; i < 20; i++) {
            System.out.println("main");
        }
    }



}
public class TestThread4 implements Runnable{
    private URL url;
    private String name;
    public TestThread4(String src,String name)  {
        try {
            this.url = new URL(src);
            this.name = name;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

    }

    /**
     * 下载图片线程执行体
     */
    @Override
    public void run() {
        try {
            HttpsURLConnection httpURLConnection = (HttpsURLConnection) url.openConnection();
            InputStream inputStream = httpURLConnection.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream(name);
            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes))!= -1){
                fileOutputStream.write(bytes,0,len);
            }
            System.out.println("下载了" + name);
            fileOutputStream.close();
            inputStream.close();
            httpURLConnection.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        TestThread4 testThread1 = new TestThread4("https://pic.netbian.com/uploads/allimg/210812/234309-1628782989c289.jpg","天空小姐姐 黑色唯美裙子.jpg");
        TestThread4 testThread2 = new TestThread4("https://pic.netbian.com/uploads/allimg/210920/165135-1632127895c615.jpg","短发女孩 袜子 窗户 云 .jpg");
        TestThread4 testThread3 = new TestThread4("https://pic.netbian.com/uploads/allimg/190824/212516-1566653116f355.jpg","下午 趴在桌子的女孩.jpg");
        new Thread(testThread1).start();
        new Thread(testThread2).start();
        new Thread(testThread3).start();


    }

}

Callable

//线程创建方式三:实现callable接口
/*
callable的好处
1.可以定义返回值
2.可以抛出异常
*/
public class TestCallable implements Callable<Boolean> {
    private URL url;
    private String name;
    public TestCallable(String src,String name)  {
        try {
            this.url = new URL(src);
            this.name = name;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

    }

    /**
     * 下载图片线程执行体
     */
    @Override
    public  Boolean call() {
        try {
            HttpsURLConnection httpURLConnection = (HttpsURLConnection) url.openConnection();
            InputStream inputStream = httpURLConnection.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream(name);
            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes))!= -1){
                fileOutputStream.write(bytes,0,len);
            }
            System.out.println("下载了" + name);
            fileOutputStream.close();
            inputStream.close();
            httpURLConnection.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable testThread1 = new TestCallable("https://pic.netbian.com/uploads/allimg/210812/234309-1628782989c289.jpg","天空小姐姐 黑色唯美裙子.jpg");
        TestCallable testThread2 = new TestCallable("https://pic.netbian.com/uploads/allimg/210920/165135-1632127895c615.jpg","短发女孩 袜子 窗户 云 .jpg");
        TestCallable testThread3 = new TestCallable("https://pic.netbian.com/uploads/allimg/190824/212516-1566653116f355.jpg","下午 趴在桌子的女孩.jpg");

        //创建执行服务:
        ExecutorService ser = Executors.newFixedThreadPool(3);
        //提交执行
        Future<Boolean> submit1 = ser.submit(testThread1);
        Future<Boolean> submit2 = ser.submit(testThread2);
        Future<Boolean> submit3 = ser.submit(testThread3);

        //获取结果
        boolean rs1 = submit1.get();
        boolean rs2 = submit1.get();
        boolean rs3 = submit1.get();

        //关闭服务
        ser.shutdownNow();
    }
}

静态代理

/**
 * 静态模式代理:
 * 真实对象和代理对象都要实现同一个接口
 * 代理对象要代理真实角色
 *
 * 好处
 * 代理对象可以做很多真实对象做不了的事情
 * 真实对象专注做自己的事情
 */

public class StaticProxy {
    public static void main(String[] args) {
        WeddingCompany weddingCompany = new WeddingCompany(new You());
        weddingCompany.Marry();
    }
}
interface Marry{
    void Marry();
}

/**
 * 真实角色
 */
class You implements Marry{
    @Override
    public void Marry() {
        System.out.println("我要结婚");
    }
}
/**
代理角色
 */
class WeddingCompany implements Marry{
    /**
     * 代理谁--》真实目标角色
     */
    public You target;

    public WeddingCompany(You target) {
        this.target = target;
    }

    @Override
    public void Marry() {
        before();
        this.target.Marry();
        after();
    }

    private void after() {
        System.out.println("结婚之后");
    }

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

Lambda表达式

/**
 * 推导lamda表达式
 */
public class TestLambda {

    //静态内部类
    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();

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

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

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


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



    }
}

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

//实现类
class Like implements ILike{
    @Override
    public void lambda() {
        System.out.println("I like lambda");
    }
}
public class TestLambda2 {
    public static void main(String[] args) {
        //lambda表达式简化
        ILove love = (int a) ->{
            System.out.println("i love you -->" + a);
        };

        //简化1.参数类型
        love = (a) ->{
            System.out.println("i love you -->" + a);
        };

        //简化2.简化括号
        love = a ->{
            System.out.println("i love you -->" + a);
        };

        //简化3.简化花括号
        love = a -> System.out.println("i love you -->" + a);

        /*
         * 总结:
         *  lambda表达式只能有一行代码的情况下才能简化成一行,如果有多行,那么就用代码块包裹
         *  前提是接口是函数式接口(就是接口只能有一个方法)
         *  多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号
         */



        love.love(2);


    }
}

interface ILove{
    void love(int a);
}

线程状态

五大状态:

创建状态

就绪状态

阻塞状态

运行状态

死亡状态

线程停止:

/**
 * 测试stop
 * 建议线程正常停止--->利用次数,不建议死循环
 * 建议使用标识位--->设置一个标志位
 * 不要使用stop或者destroy等过时或者Jdk不建议使用的方法
 */

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;
        System.out.println("子线程停止");
    }

    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();

        for (int i = 0; i < 1000; i++) {
           System.out.println("main" + i);
            if (i == 900){
                //调用stop,切换标识位,停止线程
                testStop.stop();
            }
        }


    }

线程休眠:

//模拟倒计时
public class TestSleep2 {


    public void tenDown(){
        int num = 10 ;
        while (num>=0){
            System.out.println(num--);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        }
    }


    public static void main(String[] args) {
       // new TestSleep2().tenDown();
        Date date = new Date(System.currentTimeMillis());//获取当前系统时间
        while (true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
            date = new Date(System.currentTimeMillis());//更新系统时间
        }
    }
}

线程礼让:

/**
 * 测试礼让线程
 * 礼让不一定成功,看cpu
 */
public class TestYield {
    public static void main(String[] args) {
        MyYield myYield = new MyYield();
        new Thread(myYield,"1号").start();
        new Thread(myYield,"2号").start();
    }


}

class MyYield implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始执行");
        Thread.yield();//礼让
        System.out.println(Thread.currentThread().getName() + "线程停止执行");
    }
}

线程强制执行

join合并线程,带此线程执行完成后,再执行其他线程,其他线程阻塞。

//测试join方法,想象为插队
public class TestJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println("插队了" + i);
        }
    }

    public static void main(String[] args) {
        //启动线程
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();


        //主线程
        for (int i = 0; i < 100; i++) {
            if (i==25){
                try {
                    thread.join();//插队
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("main" + i);
        }

    }
}

线程状态观测

//测试观察线程状态
public class TestState {
    public static void main(String[] args) {
        Runnable target;
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("/////////////");
        });
        //观察状态
        Thread.State state = thread.getState();
        System.out.println(state);

        //观察启动后
        thread.start();//启动线程
        state = thread.getState();
        System.out.println(state);

        while (state != Thread.State.TERMINATED){
            try {
                Thread.sleep(100);
                state = thread.getState();
                System.out.println(state);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程优先级

java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。

priority 优先级

//测试线程优先级
public class TestPriority {
    public static void main(String[] args) {
        //主线程默认优先级
        System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
        MyPriority myPriority = new MyPriority();
        Thread thread = new Thread(myPriority);
        Thread thread2 = new Thread(myPriority);
        Thread thread3 = new Thread(myPriority);
        Thread thread4 = new Thread(myPriority);
        Thread thread5 = new Thread(myPriority);
        Thread thread6 = new Thread(myPriority);
        //先设置优先级,在启动
        thread.start();
        thread2.setPriority(1);
        thread2.start();
        thread3.setPriority(3);
        thread3.start();
        thread4.setPriority(5);
        thread4.start();
        thread5.setPriority(7);
        thread5.start();
        thread6.setPriority(Thread.MAX_PRIORITY);
        thread6.start();


    }
}

class MyPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
    }
}

守护线程

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

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

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

//测试守护线程
public class TestDaemon {
    public static void main(String[] args) {
        You you = new You();
        Protect protect = new Protect();
        Thread thread = new Thread(protect);
        thread.setDaemon(true);//默认为false表示用户线程,正常线程都是用户线程
        thread.start();//守护线程启动
        new Thread(you).start();//用户线程启动

    }
}
class You implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("用户线程");
        }
        System.out.println("==========================================");
    }
}
class Protect implements Runnable{
    @Override
    public void run() {
       while (true){
           System.out.println("守护线程");
       }
    }
}

线程同步

多个线程操作同一个资源

并发

线程同步 synchronized

队列和锁

线程不安全:

//不安全的买票
//线程不安全,有负数
public class UnsafeTicket{
    public static void main(String[] args) {
        BuyTicket buyTicket = new BuyTicket();
        new Thread(buyTicket,"小红").start();
        new Thread(buyTicket,"小名").start();
        new Thread(buyTicket,"小蓝").start();
    }
}




class BuyTicket implements Runnable {
    //票
    private int ticketNums = 10;
    //外部停止方式
    boolean flag = true;

    @Override
    public void run() {
        //买票
        while (flag) {
            buy();
        }

    }

    private void buy() {
        //判断是否有票
        if (ticketNums <= 0) {
            flag = false;
            return;
        }
        //模拟延时
        try {
            Thread.sleep(00);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //买票
        System.out.println(Thread.currentThread().getName() + "拿到了" + ticketNums--);

    }
}
//不安全的取钱
public class UnsafeBank {
    public static void main(String[] args) {
        //账户
        Account account = new Account(100,"基金");
        //取钱
        Bank bank = new Bank(account,50,"小红");
        Bank bank1 = new Bank(account,100,"小蓝");
        bank.start();
        bank1.start();


    }
}


//账户
class Account{
    int money;//余额
    String name;//卡名

    public Account(int money,String name) {
        this.money = money;
        this.name = name;
    }
}

//银行取款
class Bank extends Thread{
    Account account;//账户
    //取了多少钱
    int drawingMoney;
    //现在手里有多少钱
    int nowMoney;

    public Bank(Account account,int drawingMoney,String name){
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }

//取钱
    @Override
    public void run() {
        //判断有没有钱
        if (account.money - drawingMoney < 0){
            System.out.println(Thread.currentThread().getName() + "钱不够");
            return;
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //余额
        account.money = account.money - drawingMoney ;
        //手里的钱
        nowMoney += drawingMoney;


        System.out.println("现在银行的钱" + account.money);
        //Thread.currentThread().getName() == this.getName()
        System.out.println(this.getName() + "拿了" + nowMoney);


    }
}
//线程不安全的集合
public class UnsafeList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 2000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());

    }
}

加锁

public class synTicket {
        public static void main(String[] args) {
            com.liang.syn.BuyTicket buyTicket = new com.liang.syn.BuyTicket();
            new Thread(buyTicket,"小红").start();
            new Thread(buyTicket,"小名").start();
            new Thread(buyTicket,"小蓝").start();

    }




    class BuyTicket implements Runnable {
        //票
        private int ticketNums = 10;
        //外部停止方式
        boolean flag = true;

        @Override
        public synchronized void run() {
            //买票
            while (flag) {
                buy();
            }

        }

        private void buy() {
            //判断是否有票
            if (ticketNums <= 0) {
                flag = false;
                return;
            }
            //模拟延时
            try {
                Thread.sleep(00);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //买票
            System.out.println(Thread.currentThread().getName() + "拿到了" + ticketNums--);

        }
    }
}
public class synBank {
    public static void main(String[] args) {
        //账户
        Account1 account = new Account1(100,"基金");
        //取钱
        Bank1 bank = new Bank1(account,50,"小红");
        Bank1 bank1 = new Bank1(account,100,"小蓝");
        bank.start();
        bank1.start();


    }
}


//账户
class Account1{
    int money;//余额
    String name;//卡名

    public Account1(int money,String name) {
        this.money = money;
        this.name = name;
    }
}

//银行取款
class Bank1 extends Thread{
    Account1 account;//账户
    //取了多少钱
    int drawingMoney;
    //现在手里有多少钱
    int nowMoney;

    public Bank1(Account1 account,int drawingMoney,String name){
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }

    //取钱
    //synchronized 默认锁的是本身this
    @Override
    public synchronized void run() {
        //锁的对象就是变化的量,需要增删改的对象
        synchronized (account) {
            //判断有没有钱
            if (account.money - drawingMoney < 0) {
                System.out.println(Thread.currentThread().getName() + "钱不够");
                return;
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //余额
            account.money = account.money - drawingMoney;
            //手里的钱
            nowMoney += drawingMoney;


            System.out.println("现在银行的钱" + account.money);
            //Thread.currentThread().getName() == this.getName()
            System.out.println(this.getName() + "拿了" + nowMoney);

        }
    }
}
public class synList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
            for (int i = 0; i < 1000; i++) {
                new Thread(() -> {
                    synchronized (list) {
                        list.add(Thread.currentThread().getName());
                    }
                }).start();
            }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());

        }

}

JUC安全

//测试JUC安全类型的集合
public class TestJUC {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 1000; i++) {
            new Thread(()->{
                copyOnWriteArrayList.add(Thread.currentThread().getName());
            }).start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(copyOnWriteArrayList.size());

    }
}

死锁

//死锁:多个线程互相抱着对方的资源,然后形成僵持
public class DeadLock {
    public static void main(String[] args) {
        Makeup makeup = new Makeup("1", 0);
        Makeup makeup1 = new Makeup("2", 1);
        makeup.start();
        makeup1.start();
    }

}
class Lipstick{

}
class Mirror{

}

class Makeup extends Thread{
    //需要的资源只有一份,用static来保证只有一份
    static Lipstick lipstick = new Lipstick();
    static Mirror mirror = new Mirror();
    //选择
    int choice;
    String name;

    public Makeup(String name,int choice){
        this.name = name;
        this.choice = choice;
    }


    @Override
    public void run() {
        makeup();
    }

    //互相只有对方的锁,需要拿到对方的资源
    private  void makeup(){
        if (choice == 0){
         synchronized (lipstick){
             //获得锁
            System.out.println(this.getName() + "锁");
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             synchronized (mirror){//获得另一个
                 System.out.println(this.getName() + "另一个锁");
             }
         }
        }else{
            synchronized (mirror){
                //获得锁
                System.out.println(this.getName() + "另一个锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lipstick){//获得另一个
                    System.out.println(this.getName() + "锁");
                }
            }
        }
    }



}

修改

//死锁:多个线程互相抱着对方的资源,然后形成僵持
public class DeadLock {
    public static void main(String[] args) {
        Makeup makeup = new Makeup("1", 0);
        Makeup makeup1 = new Makeup("2", 1);
        makeup.start();
        makeup1.start();
    }

}
class Lipstick{

}
class Mirror{

}

class Makeup extends Thread{
    //需要的资源只有一份,用static来保证只有一份
    static Lipstick lipstick = new Lipstick();
    static Mirror mirror = new Mirror();
    //选择
    int choice;
    String name;

    public Makeup(String name,int choice){
        this.name = name;
        this.choice = choice;
    }


    @Override
    public void run() {
        makeup();
    }

    //互相只有对方的锁,需要拿到对方的资源
    private  void makeup(){
        if (choice == 0){
         synchronized (lipstick){
             //获得锁
            System.out.println(this.getName() + "锁");
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }

         }
            synchronized (mirror){//获得另一个
                System.out.println(this.getName() + "另一个锁");
            }
        }else{
            synchronized (mirror){
                //获得锁
                System.out.println(this.getName() + "另一个锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            synchronized (lipstick){//获得另一个
                System.out.println(this.getName() + "锁");
            }
        }
    }
}

lock(锁)

//测试Lock锁
public class TestLock {
    public static void main(String[] args) {
        Testlock2 testlock2 = new Testlock2();
        new Thread(testlock2,"1").start();
        new Thread(testlock2,"2").start();
        new Thread(testlock2,"3").start();
    }
}
class Testlock2 implements Runnable{
    int tickNums = 100;


    //定义lock锁
    private final ReentrantLock reentrantLock = new ReentrantLock();

    @Override
    public void run() {
        while (true){
                reentrantLock.lock();
                try {
                    if (tickNums > 0) {
                        Thread.sleep(100);
                        System.out.println(Thread.currentThread().getName() + "" + tickNums--);
                    } else {
                        break;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            finally {
                reentrantLock.unlock();
            }
        }
    }
}

线程通信

wait();等待

notify();唤醒

管程法

//测试:生产者消费者模型-->利用缓冲区解决:管程法
//生产者,消费者,产品,缓冲区
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 = 1; i <= 100; i++) {
            container.push(new Chicken(i));
            System.out.println("生产了" + i +"只鸡");
        }
    }
}
//消费者
class Consumer extends Thread{
    SynContainer container;
    public Consumer(SynContainer container){
        this.container = container;
    }
    //消费
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println("消费了" + container.pop().id +"只鸡");
        }
    }
}
//产品
class Chicken{
    int id;//产品编号
    public Chicken(int id) {
        this.id = id;
    }
}

//缓冲区
class SynContainer{
    //需要一个容器大小
    Chicken[] chickens = new Chicken[10];
    //容器计数器
    int count = 0;

    //生产者放入产品
    public synchronized Chicken push(Chicken chicken){
        //如果容器满了,就需要等待消费者消费
        while(count == chickens.length){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //如果没有满,我们就需要丢入产品
        chickens[count] = chicken;
        count++;

        //可以通知消费者消费了!
        this.notifyAll();
        return chicken;
    }
    //消费者消费产品
    public synchronized Chicken pop() {
        //判断是否能消费
        while (count == 0) {
            //不能消费时(实际数量为0) 消费者等待 生产
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //如果可以消费
        count--;
        Chicken chicken = chickens[count];
        //吃完了通知生产
        this.notifyAll();
        return chicken;
    }



}

信号灯法

//测试生产者消费者问题2:信号灯法,标志位解决
public class TestPc2 {
    public static void main(String[] args) {
        TV tv = new TV();
        Player player = new Player(tv);
        Watcher watcher = new Watcher(tv);
        player.start();
        watcher.start();
    }

}

//生产者 演员
class Player extends Thread{
    TV tv ;
    public Player(TV tv){
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if (i%2 == 0){
                this.tv.play("节目");
            }else{
                this.tv.play("广告");
            }
        }
    }
}

//消费者 观众
class Watcher extends Thread{
    TV tv ;
    public Watcher(TV tv){
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            this.tv.watch();
        }
    }
}

//产品 节目
class TV{
    //演员表演,观众等待
    //观众观看,演员等待
    String vioce;
    boolean flag = true;

    //表演
    public synchronized  void play(String vioce){
        while (!flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("表演了" + vioce);
        //通知观众观看
        this.notifyAll();//通知唤醒
        this.vioce = vioce;
        this.flag = !this.flag;
    }

    //观看
    public synchronized void watch(){
        while (flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
            System.out.println("观看了" + vioce);
            //通知演员表演
            this.notifyAll();
            this.flag = !this.flag;
    }
}

使用线程池

//测试线程池
public class TestPool {
    public static void main(String[] args) {
        //创建线程池
        //newFixedThreadPool参数为线程池大小
        ExecutorService service = Executors.newFixedThreadPool(10);

        //执行
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());

        //关闭连接
        service.shutdownNow();

    }

}

class  MyThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 1; i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }
}

文章作者: 半页
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 半页 !
评论
  目录