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 + "\t取出:" + 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拿到第二把钥匙!
(一直在运行中,程序没有结束!)

原文地址:https://www.cnblogs.com/snzd9958/p/9792664.html

时间: 2024-08-30 01:17:04

Thread实现多线程、死锁、同步锁的相关文章

传统多线程之同步锁(二)

一. 线程安全 线程安全问题是指程序中公用的东西被多个线程访问,比如:类的静态变量 二. 同步锁 有什么办法可以解决线程安全问题呢?那就是在程序中加锁 Java有两种加锁的方法: 1. 在代码块中加锁 synchronized (this) { ... } 2. 在方法上加锁 public synchronized void xxx(){ ... } 示例代码: public class TraditionalThreadSynchronized { public static void mai

多线程安全----同步锁(互斥锁)

多条线程抢夺同一资源时,经常需要加锁,保证同一时间只能有一条线程操作一个资源. 同步锁就是互斥锁 格式:@synchronized (token) { } token:锁对象,要使用全局的对象,建议使用self {} 要加锁的代码段 注意点:加多把锁是无效的. 要注意加锁的位置. 互斥锁的优点: 能有效防止多线程因抢夺资源造成的数据安全问题 互斥锁的缺点:需要消耗大量的cpu资源 互斥锁使用的前提:多条线程抢夺同一块资源 相关术语:线程同步 线程同步就是多条线程在同一条线上执行(按顺序的执行任务

多线程 - 线程同步锁(lock、Monitor)

1. 前言 多线程编程的时候,我们不光希望两个线程间能够实现逻辑上的先后顺序运行,还希望两个不相关的线程在访问同一个资源的时候,同时只能有一个线程对资源进行操作,否则就会出现无法预知的结果. 比如,有两个线程需要对同一个计数器加1,我们希望结果是计数器最终加2,但可能同时获取到了这个计数器,第一个线程对计数器加1,但第二个线程并不知道,于是重新对计数器加1,导致最终计数器损失了一个计数.为了解决这个问题,就必须在获取该计数器前锁定,防止其他线程再次获取,直到处理完成后再释放. Monitor.l

线程同步锁、死锁、递归锁、信号量、GIL

目录 线程同步锁.死锁.递归锁.信号量.GIL 一.同步锁 二.死锁 三.递归锁(Rlock) 四.信号量(Semphare) 五.GIL(全局解释器锁) io密集型 计算密集型 线程同步锁.死锁.递归锁.信号量.GIL 一.同步锁 所有线程同一时间读写同一个数据,有的线程已经对数据进行修改了,造成有的线程拿到的数据时旧的数据,而不是修改后的数据,造成结果不正确,于是引入了同步锁解决问题, 同步锁的原理是同一时间只能有一个线程读写数据. 锁通常被用来实现对共享资源的同步访问.从threading

Java多线程同步锁的理解

ava 多线程中同步锁的主要通过synchronized的关键字来实现的.让我们从一个买票程序说起吧. package com.day04; /** * * @author Administrator 问题描述:使用多线程的方式来模拟多个窗口买票 * */ public class SaleWindow implements Runnable { // 初始化票数10 private int ticket = 10; @Override public void run() { // 获取线程的名

多线程编程-- part5 锁的种类以及辨析

java中的锁,可以分为同步锁和JUC包中的锁. 同步锁 通过synchronized关键字进行同步,实现对竞争资源的互斥访问的锁,. 原理:对于每一个对象,有且只有一个同步锁,在同一时间点,所有的线程中有且只有一个能获取该同步锁,获取到同步锁的就可以被CPU进行调度,其他线程必须等待,直到获取到同步锁之后才能继续运行,这就是多线程通过同步锁进行同步的原理. JUC包中的锁:java.util.concurrent 功能更强大,使用当然更复杂. JUC包中锁,包括:lock接口,readWrit

001-多线程-锁-架构【同步锁、JUC锁】

一.概述 Java中的锁,可以分为"同步锁"和"JUC包中的锁". 1.1.同步锁 即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁.Java 1.0版本中就已经支持同步锁了. 同步锁的原理是,对于每一个对象,有且仅有一个同步锁:不同的线程能共同访问该同步锁.但是,在同一个时间点,该同步锁能且只能被一个线程获取到.这样,获取到同步锁的线程就能进行CPU调度,从而在CPU上执行:而没有获取到同步锁的线程,必须进行等待,直到获取到同步锁之后才

java基础知识回顾之java Thread类学习(五)--java多线程安全问题(锁)同步的前提

这里举个例子讲解,同步synchronized在什么地方加,以及同步的前提: * 1.必须要有两个以上的线程,才需要同步. * 2.必须是多个线程使用同一个锁. * 3.必须保证同步中只能有一个线程在运行,锁加在哪一块代码 那么我们要思考的地方有:1.知道我们写的哪些是多线程代码 2.明确共享数据 3.明确多线程运行的代码中哪些语句是操作共享数据的.. 4.要确保使用同一个锁. 下面的代码:需求:两个存户分别往银行存钱,每次村100块,分三次存完. class bank{ private int

并发&amp;并行 同步&amp;异步 GIL 任务 同步锁 死锁 递归锁

# 并发&并行 同步&异步 GIL 任务 同步锁 死锁 递归锁 # 并发:是指系统具有处理多个任务(动作)的能力 # 并行:是指系统具有 同时 处理多个任务(动作)的能力 # 同步:当进程执行到一个IO(等待外部数据)的时候,需要等待外部数据接收完 # 异步:当进程执行到一个IO(等待外部数据)的时候,不需要等待外部数据接收完,还可以做其它的处理 # GIL: 全局解释器锁 在python中,无论你启多少个线程,你有多少个cpu,python在执行的时候在同一时刻只请允许一个线程运行 #