package java3;
/**
* 实现Runnable接口的方式
* 1.问题:卖票过程中出现了重票or错票的问题->线程安全问题
* 2.问题原因:某个线程操作车票时,操作尚未完成时,其他线程参与进来操作车票
* 3.如何解决:当一个线程在操作ticket时,另外的线程不能参与进来,直到当前线程操作结束,其他线程才可以开始操作ticket
* 即使线程A出现了阻塞也不能有其他线程参与进来
* 4.在Java中通过同步机制来解决线程安全问题
*
* 方式1:同步代码块
* synchronized(同步监视器){
* 需要同步的代码
* }
* 说明:操作共享数据的代码就是需要被同步的代码->不能多也不能少
* 共享数据:多个线程共同操作的数据
* 同步监视器:俗称,“锁”,任何一个类的对象都可以充当锁
* 要求:多个线程用同一把锁
*
* 补充:在使用Runnable接口实现多线程的过程中,可以考虑使用this来充当同步监视器
* 在继承Thread类实现多线程的过程中,慎重使用this充当同步监视器
* 方式2:同步方法
* 如果操作共享数据的代码完整的声明在一个方法中,不妨将该方法声明为同步的
*
* 5.使用同步的方式,解决了线程的安全问题-----好处
* 操作同步代码时,只能有一个线程参与,相当于单线程过程,效率低-------局限性
* @author Baobao
* @create 2021-08-01 17:44
*/
class Window1 implements Runnable{
private int ticket=100;
Object obj=new Object();
@Override
public void run() {
while (true){
synchronized (this){
if(ticket>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":卖票,票号:"+ticket);
ticket--;
}else {
break;
}
}
}
}
}
public class WindowTest1 {
public static void main(String[] args) {
Window1 w1=new Window1();
Thread t1 = new Thread(w1);
Thread t2 = new Thread(w1);
Thread t3 = new Thread(w1);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
package java3;
/**
*
* 使用同步方法来解决实现Runnable接口
*
* 同步方法仍然需要同步监视器,只是不需要显式声明
* 非静态的同步方法,使用的监视器是this
* 静态的同步方法,使用的监视器是当前类本身
* @author Baobao
* @create 2021-08-01 22:21
*/
class Window2 implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true) {
show();
}
}
private synchronized void show() {//同步监视器:this
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":卖票,票号:" + ticket);
ticket--;
}
}
}
public class WindowTest2 {
public static void main(String[] args) {
Window2 w1=new Window2();
Thread t1 = new Thread(w1);
Thread t2 = new Thread(w1);
Thread t3 = new Thread(w1);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
package java3;
/**
*
* 创建3个窗口买票,总票数为100张,使用继承Thread类的方式
*
* 使用同步代码块来解决继承Thread类的方式
*
* @author Baobao
* @create 2021-08-01 17:17
*/
class Window extends Thread{
private static int ticket=100;
static Object obj=new Object();
@Override
public void run() {
while(true){
synchronized (Window.class){
if(ticket>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName()+":卖票,票号为:"+ticket);
ticket--;
}else{
break;
}
}
}
}
}
public class WindowTest {
public static void main(String[] args) {
Window w1=new Window();
Window w2=new Window();
Window w3=new Window();
w1.setName("窗口1");
w2.setName("窗口2");
w3.setName("窗口3");
w1.start();
w2.start();
w3.start();
}
}