多线程实现方式?如何启动多线程?什么情况下会发生线程安全问题?如何解决线程安全问题?

一、实现多线程的几种方式

1、继承Threa类

代码案例如下

任务1

package com.xc.threadDemo;

public class Task1 extends Thread{
    @Override
    public void run() {
        for(int i = 1; i < 10; i++) {
            System.out.println("i===================================" + i);
        }
    }
}

任务2

package com.xc.threadDemo;

public class Task2 extends Thread{
    @Override
    public void run() {
        for(int j = 1; j < 10; j++) {
            System.out.println("j=" + j);
        }
    }
}

线程执行类

package com.xc.threadDemo;

public class Test {
    public static void main(String[] args) {
        Task1 task1 = new Task1();
        Task2 task2 = new Task2();
        //如果调用run方法,程序就会从上至下执行
        task1.run();
        task2.run();
        //只有调用start方法,启动而不是运行线程,两个线程才会同时执行
        task1.start();
        task2.start();
    }
}

 

2、实现Runnable接口

代码案例如下

任务1

package com.xc.threadDemo2;

public class Task1 implements Runnable{

    @Override
    public void run() {
        for(int i = 1; i < 1000; i++) {
            System.out.println("i===================================" + i);
        }
    }
}

 

任务2

package com.xc.threadDemo2;

public class Task2 implements Runnable{

    @Override
    public void run() {
        for(int j = 1; j < 1000; j++) {
            System.out.println("j=" + j);
        }
    }
}

 

线程执行类

package com.xc.threadDemo2;

public class Test {
    public static void main(String[] args) {
        Runnable task1 = new Task1();
        Runnable task2 = new Task2();
        Thread thread1 = new Thread(task1);
        Thread thread2 = new Thread(task2);
        thread1.start();
        thread2.start();
    }
}

 

二、如何启动线程

如上面的案例所示

1、如果是继承Thread类,启动线程使用对象调用start方法即可

2、如果是实现Runnable接口,启动线程的方式相对复杂一点,但是这是实际开发中使用最多的方式,因为Java是单继承,一旦继承了Thread类,就无法继承其他类

 

三、什么情况下会发生线程安全问题

当多个线程访问同一个共享数据时,有可能会出现线程安全问题

例如如下案例(火车票购票系统)

 

 

package com.xc.threadDemo3;

public class TicketSystem extends Thread{
    //售票系统只有200张票
    public static int ticketNum = 200;
    
    @Override
    public void run() {
        try {
            //模拟一个售票窗口有1000人排队买票
            for(int i = 1; i <= 1000; i++) {
                if(ticketNum > 0) {
                    ticketNum--;
                    System.out.println("售票窗口:"+Thread.currentThread()+"通知:恭喜您,成功抢到票,还剩下"+ticketNum+"张票");
                }
                //模拟每个人买票之后与下一个人买票之前的时间间隔
                Thread.sleep(500);
            }
        }catch(Exception e) {
            System.out.println("抢票失败,请检查您的网络!");
        }
    }

}

 

package com.xc.threadDemo3;

public class Test {
    public static void main(String[] args) {
        //模拟同时有三个售票窗口,分别有1000人同时在排队买票
        TicketSystem ticketSystem1 = new TicketSystem();
        TicketSystem ticketSystem2 = new TicketSystem();
        TicketSystem ticketSystem3 = new TicketSystem();
        ticketSystem1.start();
        ticketSystem2.start();
        ticketSystem3.start();
    }
}

 

 执行结果

售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下8张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下8张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下7张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下5张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下5张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下4张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下3张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下3张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下2张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下0张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下0张票

 

结论:

可以看到同一张票,被卖出去两次,这是不允许出现的情况

 

四、如何解决线程安全问题

 

解决方案就是加锁,在关键的地方加锁,就可以解决这样的问题,代码如下

 

package com.xc.threadDemo3;

public class TicketSystem extends Thread{
    //售票系统只有200张票
    public static int ticketNum = 200;
    
    @Override
    public void run() {
        try {
            //模拟一个售票窗口有1000人排队买票
            for(int i = 1; i <= 1000; i++) {
                synchronized (TicketSystem.class) {
                    if(ticketNum > 0) {
                        ticketNum--;
                        System.out.println("售票窗口:"+Thread.currentThread()+"通知:恭喜您,成功抢到票,还剩下"+ticketNum+"张票");
                    }
                    //模拟每个人买票之后与下一个人买票之前的时间间隔
                    Thread.sleep(500);
                }
            }
        }catch(Exception e) {
            System.out.println("抢票失败,请检查您的网络!");
        }
    }

}

 

执行结果

售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下199张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下198张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下197张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下196张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下195张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下194张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下193张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下192张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下191张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下190张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下189张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下188张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下187张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下186张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下185张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下184张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下183张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下182张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下181张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下180张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下179张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下178张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下177张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下176张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下175张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下174张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下173张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下172张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下171张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下170张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下169张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下168张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下167张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下166张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下165张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下164张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下163张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下162张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下161张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下160张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下159张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下158张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下157张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下156张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下155张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下154张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下153张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下152张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下151张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下150张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下149张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下148张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下147张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下146张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下145张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下144张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下143张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下142张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下141张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下140张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下139张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下138张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下137张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下136张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下135张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下134张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下133张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下132张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下131张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下130张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下129张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下128张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下127张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下126张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下125张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下124张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下123张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下122张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下121张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下120张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下119张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下118张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下117张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下116张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下115张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下114张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下113张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下112张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下111张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下110张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下109张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下108张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下107张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下106张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下105张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下104张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下103张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下102张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下101张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下100张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下99张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下98张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下97张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下96张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下95张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下94张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下93张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下92张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下91张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下90张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下89张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下88张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下87张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下86张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下85张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下84张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下83张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下82张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下81张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下80张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下79张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下78张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下77张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下76张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下75张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下74张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下73张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下72张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下71张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下70张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下69张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下68张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下67张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下66张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下65张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下64张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下63张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下62张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下61张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下60张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下59张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下58张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下57张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下56张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下55张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下54张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下53张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下52张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下51张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下50张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下49张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下48张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下47张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下46张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下45张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下44张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下43张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下42张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下41张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下40张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下39张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下38张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下37张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下36张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下35张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下34张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下33张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下32张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下31张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下30张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下29张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下28张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下27张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下26张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下25张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下24张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下23张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下22张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下21张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下20张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下19张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下18张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下17张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下16张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下15张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下14张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下13张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下12张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下11张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下10张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下9张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下8张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下7张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下6张票
售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下5张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下4张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下3张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下2张票
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下1张票
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下0张票

总结

1、为什么同步代码块包裹的部分是 

if(ticketNum > 0) {
                        ticketNum--;
                        System.out.println("售票窗口:"+Thread.currentThread()+"通知:恭喜您,成功抢到票,还剩下"+ticketNum+"张票");
                    }
                    //模拟每个人买票之后与下一个人买票之前的时间间隔
                    Thread.sleep(500);

其他部分为什么不包裹?

 

因为没有必要包裹,排队的时候,并不会对共享数据产生影响,随意插队并不会对售票系统的票造成什么干扰,只有多个窗口同时操作一张票的时候,才会产生票数错乱的问题

 

所以同步代码块包裹的地方,才是关键点所在

 

打一个形象的比喻:

如果很多人排队小便,所有排队的人,在关键的时候,也就是小便的时候,才需要锁住,也就是其他人不能共享便池,其他不能进来,但是脱裤子和穿裤子的时候,就没偶遇必要占用坑位了,这个时候可以到旁边去进行,所以穿裤子不用加锁

 

2、为什么会产生数据安全问题,也即是票数错乱的问题?

 

比如售票系统只剩下最后一张票,窗口1有人在买这张票,然后进入判断你条件:if(ticketNum > 0),发现满足条件,但是当票数还没有执行ticketNum--;操作时,第二个人就开始在窗口2买票,此时他会发现还剩余一张,所以就进行了买票,但实际上第一个人已经买走了,只是票数没有减少而已,这样就会发生数据错乱

 

补充

什么场景下会用到多线程

1、例如我们一开始学习过的《坦克大战》《飞机大战》等Java游戏程序,我方飞机、敌机、子弹、背景就分别是一个线程,分别对应一个Java类,所以开发这种游戏一定要使用多线程

2、不管是单核处理器,还是多核处理器,都是可以实现多线程,如果是单核处理器,当你执行多个线程时,就会出现卡顿,程序没有响应

3、操作系统指控cpu(硬件)来完成任务执行,使用时间调度器,但是时间无法均匀分配,调度cpu进行多线程执行,一会执行以下任务1,然后执行以下任务2

 

疑问

Java是站在了巨人的肩膀上,那么多线程底层的代码逻辑是如何实现的?

posted @ 2020-08-01 15:00  Java精进之路  阅读(785)  评论(0编辑  收藏  举报