• Thread实现多线程、死锁、同步锁


    1、实现一个类MyThread继承Thread并重写run()方法
    启动线程方法:实例化MyThread对象,并调用start()方法
    多个线程之间交替执行(抢时间片)
    主线程(main方法)有优先运行的权限,但并不绝对

    2、实现一个类MyThread实现Runnable接口下的run()方法
    启动线程方法:实例化MyThread对象mt,并将mt作为实例化Thread的参数,再通过Thread对象调用start()方法
    MyThread mt = new MyThread();
    Thread t = new Thread(mt);
    t.start();

    实现点击按钮,球向前慢慢滚动的效果:
    public class Test extends JFrame{

        private MyPanel mp;
        public static void main(String[] args) {
            new Test().setVisible(true);

        }
        private JPanel panel;
        private JButton btn;
        public Test() {
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
            panel = new JPanel();
            panel.setLayout(new BorderLayout());
            setBounds(300, 100, 600, 300);
            this.setContentPane(panel);
            
            mp = new MyPanel();
            panel.add(mp);
            
            btn = new JButton("开始");
            
            btn.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    
                    Thread t = new Thread(mp);
                    t.start();
                    
                }
            });
            panel.add(btn,BorderLayout.SOUTH);
        }
        
        private class MyPanel extends JPanel implements Runnable{

            private int x = 100;
            public void paint(Graphics g) {
                super.paint(g);
                g.fillOval(x, 80, 50, 50);
            }
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    x += 5 ;
                    try {
                        Thread.sleep(150);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    repaint();
                }
                
            }
        }
    }

    3、使用匿名类,继承Thread,重写run()方法,直接在run()方法中写业务代码
    匿名类的一个好处是可以很方便的访问外部的局部变量
    public class TestThread {
      
        public static void main(String[] args) {
              
            Hero gareen = new Hero();
            gareen.name = "盖伦";
            gareen.hp = 616;
            gareen.damage = 50;
      
            Hero teemo = new Hero();
            teemo.name = "提莫";
            teemo.hp = 300;
            teemo.damage = 30;
              
            Hero bh = new Hero();
            bh.name = "赏金猎人";
            bh.hp = 500;
            bh.damage = 65;
              
            Hero leesin = new Hero();
            leesin.name = "盲僧";
            leesin.hp = 455;
            leesin.damage = 80;
              
            //匿名类
            Thread t1= new Thread(){
                public void run(){
                    //匿名类中用到外部的局部变量teemo,必须把teemo声明为final
                    //但是在JDK7以后,就不是必须加final的了
                    while(!teemo.isDead()){
                        gareen.attackHero(teemo);
                    }              
                }
            };
             
            t1.start();
              
            Thread t2= new Thread(){
                public void run(){
                    while(!leesin.isDead()){
                        bh.attackHero(leesin);
                    }              
                }
            };
            t2.start();
             
        }
          
    }

    注意: 启动线程是start()方法,run()并不能启动一个新的线程

    常见线程方法:

    sleep    当前线程暂停
    Thread.sleep(1000); 表示当前线程暂停1000毫秒 ,其他线程不受影响 

    join    加入到当前线程中
    Thread t1= new Thread(){
                public void run(){
                    while(!teemo.isDead()){
                        gareen.attackHero(teemo);
                    }
                }
            };
    t1.start();
    try {
     //main线程在运行时,t1线程加入到main线程中来,只有t1线程运行结束,才会继续往下走
          t1.join();
    } catch (InterruptedException e) {
    e.printStackTrace();

    }

    setPriority    线程优先级
    当线程处于竞争关系的时候,优先级高的线程会有更大的几率获得CPU资源 
    Thread t1 = new Thread();
    Thread t2 = new Thread();
    t1.setPriority(Thread.MAX_PRIORITY);最大为10
    t2.setPriority(Thread.MIN_PRIORITY);最小为0

    yield    临时暂停    
    当前线程,临时暂停,使得其他线程可以有更多的机会占用CPU资源

    setDaemon    守护线程
    如果一个进程只剩下守护线程,那么进程就会自动结束。


    线程同步

    没有实现同步
    public class Bank {

        public static void main(String[] args) {
            new Bank().way();

        }

        public void way() {
            Family f = new Family();
            Thread t1 = new Thread(f, "丈夫");

            //new Thread(f, "线程名称");
            Thread t2 = new Thread(f, "妻子");
            t1.start();
            t2.start();
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            while (true) {
                if (f.times >= 2) {
                    f.show();
                    break;
                }
            }

        }

        private class Family implements Runnable {
            private int totalMoney;
            private int getMoney;
            private int currentMoney;
            private int times = 0;
            private Object key = new Object();

            public Family() {
                totalMoney = 5000;
                getMoney = 2000;
                currentMoney = 0;
            }

            @Override
            public void run() {

                //Thread.currentThread()当前线程
                System.out.println(Thread.currentThread().getName() + "---取了" + getMoney + "元");
                //给取出的钱重新赋值
                currentMoney += getMoney;
                
                //银行存款剩余
                int tem = totalMoney - getMoney;
                
                //在银行存款变换之前,线程沉睡1s,这时,时间片被另一个线程抢走
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                 //给银行存款重新赋值
                totalMoney = tem;
                times++;
            }
            
            public void show() {
                System.out.println("银行存款剩余:" + totalMoney + " 取出:" + currentMoney);
            }
        }
    }
    运行:
    丈夫---取了2000元
    妻子---取了2000元
    银行存款剩余:3000    取出:4000

    添加同步锁:
        方法一:
            //对象必须在run()方法体外面
            private Object key = new Object();

            public void run() {
                //synchronized( 可以是任意对象,例如:this)
                synchronized (key) {
                    System.out.println(Thread.currentThread().getName() + "---取了" + getMoney + "元");
                    currentMoney += getMoney;
                    int tem = totalMoney - getMoney;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    totalMoney = tem;
                    times++;
                }

            }

        方法二:
            public void run() {
                
                syn();

            }
            public synchronized void syn() {
                System.out.println(Thread.currentThread().getName() + "---取了" + getMoney + "元");
                currentMoney += getMoney;
                int tem = totalMoney - getMoney;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                totalMoney = tem;
                times++;
            }
    运行:
    丈夫---取了2000元
    妻子---取了2000元
    银行存款剩余:1000    取出:4000


    死锁

    1. 线程1 首先占有对象1,接着试图占有对象2
    2. 线程2 首先占有对象2,接着试图占有对象1
    3. 线程1 等待线程2释放对象2
    4. 与此同时,线程2等待线程1释放对象1
    就会。。。一直等待下去,直到天荒地老,海枯石烂,山无棱 ,天地合。。。

    public class Test04 {

        public static void main(String[] args) {
            new Test04();

        }
        public Test04() {
            MyThread mt = new MyThread();
            Thread t1 = new Thread(mt,"A");
            Thread t2 = new Thread(mt,"B");
            t1.start();t2.start();
        }
        public class MyThread implements Runnable{
            private Object o1 = new Object();
            private Object o2 = new Object();
            private boolean b = false;
            @Override
            public void run() {
                if(b) {
                    b = !b;
                    synchronized (o1) {
                        System.out.println(Thread.currentThread().getName()+"拿到第一把钥匙!");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        synchronized (o2) {
                            System.out.println(Thread.currentThread().getName()+"拿到第二把钥匙!");
                        }
                    }
                }else {
                    b = !b;
                    synchronized (o2) {
                        System.out.println(Thread.currentThread().getName()+"拿到第二把钥匙!");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        synchronized (o1) {
                            System.out.println(Thread.currentThread().getName()+"拿到第一把钥匙!");
                        }
                    }
                }
                
            }
            
        }

    }
    运行:
    B拿到第一把钥匙!
    A拿到第二把钥匙!
    (一直在运行中,程序没有结束!)

  • 相关阅读:
    浅谈 js字符串 trim 方法之正则篇
    各大型网站使用的服务器空间运行环境盘点
    博客打开慢?请禁用WordPress默认的谷歌字体!
    巧妙设计:让页面活起来
    最流行的JavaScript库jQuery不再支持旧版IE
    Spring各个版本源码下载地址
    mysql 修改字符集
    Spring AOP aspectjweaver.jar与aopalliance-1.0.jar 下载地址
    <<Java | Java正则表达式 | 学习总结>>
    <Java并发编程实战 | 前言 | 学习总结>
  • 原文地址:https://www.cnblogs.com/snzd9958/p/9792664.html
Copyright © 2020-2023  润新知