TheStar

导航

< 2025年1月 >
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8
统计
 

实现线程的方式是一,继承Thread类,重写父类的run()方法

二,实现接口Runnable中的run()方法。

下面是简单的例子

例子1:银行存取钱问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package com.direct.demo;
 
public class Bank {
    private static int money;
    public int getMoney(){
        return money;
    }
    public void saveMoney(int m){
        synchronized (this) {
            System.out.println("存钱后的总金额:"+(money+=m));         
        }
    }
    public void drawMoney(int m){
        synchronized (this) {
            Bank bank = new Bank();
            if (bank.getMoney()<=0) {
                System.out.println("没得钱,取个pi");
            }else {
                System.out.println("取钱后剩的总金额:"+(money-=m));        
            }
        }
    }
     
    public static void main(String[] args) {
        Man m1 = new Man();
        Women w = new Women();
        Thread t1 = new Thread(m1);
        Thread t2 = new Thread(m1);
        Thread t3 = new Thread(m1);
        Thread t4 = new Thread(w);
        Thread t5 = new Thread(w);
        Thread t6 = new Thread(w);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
        t6.start();
        }
 
}
 
class Man implements Runnable{
    private Bank bank = new Bank();
 
    public void run() {
        int m = 100;
        int i=0;
        while (i<5) {
                bank.saveMoney(m);
                i++;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }  
        }
    }
}
class Women implements Runnable{
    private Bank bank = new Bank();
 
    public void run() {
        int m = 100;
        int i=0;
        //bank.getMoney()>0
        while (i<5) {
                    bank.drawMoney(m);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        i++;
        }
    }
     
}

  例子2:生产者与消费者问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package com.direct.demo;
 
public class Clerk {
    private int product = -1;
     
    //这个方法由生产者调用
    public synchronized void setProduct(int product){
        if (this.product != -1) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.product = product;
        System.out.printf("生产者设定 (%d)%n",this.product);
        notify();
    }
     
    //这个方法由消费者调用
    public synchronized int getProduct(){
        if (this.product==-1) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        int p = this.product;
        System.out.printf("消费者取走 (%d)%n",this.product);
        this.product = -1;
        notify();
        return p;
    }
 
    public static void main(String[] args) {
        Clerk clerk = new Clerk();
        new Thread(new ProducerInt(clerk)).start();
        new Thread(new ConsumerInt(clerk)).start();
    }
     
}
 
class  ProducerInt implements Runnable{
    private Clerk clerk;
    public ProducerInt(Clerk clerk){
        this.clerk = clerk;
    }
    public void run() {
        System.out.println("生产者开始生产整数了..................");
        for (int product = 1; product <= 10; product++) {
            try {
                Thread.sleep((int)Math.random()*300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            clerk.setProduct(product);
        }
    }
     
}
 
class ConsumerInt implements Runnable{
    private Clerk clerk;
    public ConsumerInt(Clerk clerk){
        this.clerk = clerk;
    }
    public void run() {
        System.out.println("消费者开始消耗整数........");
        for (int i = 1; i <=10 ; i++) {
            try {
                Thread.sleep((int)Math.random()*300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            clerk.getProduct();//从店员取走整数
        }
    }
     
}

例子3:购票窗口实现票数同步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.direct.demo;
 
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
public class ThreadTicket {
    public static void main(String[] args) {
        Booking b1 = new Booking("军人售票口");
        Booking b2 = new Booking("学生售票口");
        Booking b3 = new Booking("老年人售票口");
        Booking b4 = new Booking("网上售票口");
        b1.start();
        b2.start();
        b3.start();
        b4.start();
    }
}
 
/*
 * 多窗口卖票系统。多线程
 * 票数为静态的,共享数据
 * synchronized(对象){}代码块中的内容是加锁的,
 * 即当一个线程在使用时,其他线程不可以进入。
 * 使得共享资源数据的安全。
 */
class Booking extends Thread{
    public  Booking(String name){
        super(name);
    }  
    static  int ticket = 50;//票数共50张
    Lock lock = new ReentrantLock();//明锁     * Lock是个接口,只能实例化它的子类
     * 明锁适合高并发,上万
     * 暗锁适合并发率不高时,效率高
     */
     
    //重写run方法,
    public void run(){         
            while(ticket>0){
                    synchronized (Booking.class) {
                        if (ticket>0) {
                            System.out.println(super.getName()+"窗口---->卖出的车票号No."+ticket);
                            ticket--;
                        }else {
                            System.out.println(super.getName()+"票已售罄!!!");
                        }              
                     try {
                        sleep(100);//睡100毫秒,抛出多线程异常
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
               }
                    /*lock.lock();//加锁,锁定以下代码
                    if (ticket>0) {
                        System.out.println(super.getName()+"卖票:"+ticket);
                        ticket--;
                    }else {
                        System.out.println(super.getName()+"票已售罄!!!");
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    lock.unlock();//解锁
*/      }      
         
    }
}

/*
* ReentrantLock根据传入构造方法的布尔型参数实例化出Sync的实现类FairSync和NonfairSync
* ,分别表示公平的Sync和非公平的Sync。
* 由于ReentrantLock我们用的比较多的是非公平锁

ReentrantLock 和synchronized 均为重入锁

* 1. ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。

2. ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。

3. ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。

 对ReentrantLock的可重入锁这篇博客使用简单的例子进行讲解,  http://blog.csdn.net/yanyan19880509/article/details/52345422

例子4:线程中sleep()和wait()方法测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.direct.demo;
 
public class TestSleepaWait {
    public static void main(String[] args) {
        new Thread(new Thread1()).start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(new Thread2()).start();
    }
     
}
 
class Thread1 implements Runnable{
    public void run() {
        synchronized (TestSleepaWait.class) {
            System.out.println("Thread1 is start........");
            System.out.println("Thread1 is wait..............");
            try {
                //调用wait方法,线程会放弃对象锁,进入等待对象的等待锁定池
                TestSleepaWait.class.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread1 is go on........");
            System.out.println("Thread1 is over!");        
        }      
    }      
}
 
class Thread2 implements Runnable{
 
    @Override
    public void run() {
        synchronized (TestSleepaWait.class) {
            System.out.println("Thread2 is enter..........");
            System.out.println("Thread2 is sleep.......");
            //只有针对对象调用notify()方法后本线程才进入对象锁定池
            //准备获取对象进入运行状态
            TestSleepaWait.class.notify();
            //===============
            //如果把上句注释掉。即对象锁调用了wait方法,但是没有调用notify
            //程序就一致处于挂起状态
            try {
                Thread.sleep(5000);
                //sleep方法暂停执行时间,让出CPU,监控状态保持,
                //时间到 了就回复运行, 不会释放对象锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread2 is going on..........");
            System.out.println("Thread2 is over!!!!");
        }
         
    }
     
} 

例子5:sleep()实现对象存取值

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.direct.demo;
 
public class ThreadCom {
    public static void main(String[] args) {
        Person person = new Person();
          new Thread(new Producer(person)).start();
          new Thread(new Consumer(person)).start();
    }
 
}
 
class Person{
    private String name = "张杰";
    private String sex = "男";
    public synchronized void put(String name,String sex){
        this.name = name;
        this.sex = sex;
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //方法加锁
    public synchronized void get(){
        System.out.println(name+"----->"+sex);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
 
class Consumer implements Runnable{
    Person person;
    public Consumer(Person person){
        this.person = person;
    }
    public void run() {
        while(true){
            person.get();
        }
    }
}
 
class  Producer implements Runnable{
    Person person;
    public Producer(Person person){
        this.person = person;
    }
    public void run() {
        int i = 0;
        while (true) {
            if (i==0) {
                person.put("谢娜", "女");
            }else {
                person.put("张杰", "男");
            }
            i = (i+1)%2;//奇数和偶数
        }
         
    }
     
}   

 

例子6:死锁发生条件

在写代码时要避免死锁

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.direct.demo;
 
public class DeadLock {
    public static void main(String[] args) {
        ThreadLock tl = new ThreadLock(true);
        ThreadLock tl2 = new ThreadLock(false);
        new Thread(tl).start();
        new Thread(tl2).start();
    }
}
 
/*
 * 死锁的产生条件:
 * 1、至少一个资源共享
 * 2、至少有一个线程(任务),必须持有资源,且等待获取别的线程持有的资源
 * 3、任务抢不到资源
 * 4、必须有无限循环
 * (1) 互斥条件:一个资源每次只能被一个进程使用。
 * (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
 * (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
 * (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
 * 举例说明:不可剥夺资源A、B,进程C、D
 * 不可剥夺资源:一个进程申请了之后,不能强制收回,只能进程结束之后自动释放。内存是可剥夺资源
 * 进程C申请了资源A,进程D申请了资源B。
 * 接下来进程C的操作需要用到资源B,进程D的操作需要用到资源A
 * 但是C、D都得不到资源,就引发了死锁
 */
 
class Lock{
    static Object lockOne = new Object();//资源A
    static Object lockTwo = new Object();//资源B
}
 
 
class ThreadLock implements Runnable{
    private boolean flag;
    public ThreadLock(boolean flag){
        this.flag = flag;
    }
    @Override
    public void run() {
        if(flag){
            while (true) {
                synchronized (Lock.lockOne) {
                    System.out.println(" this is lockOne");
                    synchronized (Lock.lockTwo) {
                        System.out.println("this is lockTwo");
                    }
                }
            }
        }else {
            while (true) {
                synchronized (Lock.lockTwo) {
                    System.out.println(" 这是 lockTwo");
                    synchronized (Lock.lockOne) {
                        System.out.println("这是 lockOne");
                    }
                }
            }
        }
    }
     
     
}

 

posted on   TheStar  阅读(30626)  评论(1编辑  收藏  举报
编辑推荐:
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 使用 Dify + LLM 构建精确任务处理应用
 
点击右上角即可分享
微信分享提示