欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

关于多线程两种方法的思考 卖票问题 同步代码块加锁问题

程序员文章站 2022-04-09 20:29:15
上面是继承Thread的方法 这种方法较为简单,只要继承后复写run方法即可,缺点是已经继承别的类就不能在继承了,有局限性。对单一对象中成员进行操作的多线程需要静态static关键字 下面是实现implements Runnable方法 锁可以在方法上,也可以用同步代码块,同步代码块较好,可以局部锁 ......
package com.swift.duoxiancheng;

class Ticket extends Thread {
    Ticket(String name) {
        super(name); // 构造函数:设置线程名称
    }

    public static int ticket = 1000;

    @Override
    public void run() {

        while (true) {
            synchronized ("锁") {
                if (ticket > 0) {
                    ticket--;
                    System.out.println(Thread.currentThread().getName() + "还有余票数:" + ticket);
                }
            }
        }
    }

    public synchronized void sellTickets() {

    }
}

public class ThreadTest_Jicheng {
    public static void main(String[] args) {
        // 一種是多個線程對應一個對象(如賣票),一種是多個線程對應多個對象(如socket線程)
        Ticket t1 = new Ticket("賣票窗口1");
        Ticket t2 = new Ticket("賣票窗口2");
        Ticket t3 = new Ticket("賣票窗口3");
        Ticket t4 = new Ticket("賣票窗口4");
        // 上面這種賣票是生成4個對象,每個對象有1000張票要賣出,只是因為線程得到CPU分配有先有后
        // 用靜態成員變量共享1000張票,票不在對象的對空間,而在內存方法區,同步問題要解決

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        System.out.println("Hello World!");
    }
}

上面是继承Thread的方法

这种方法较为简单,只要继承后复写run方法即可,缺点是已经继承别的类就不能在继承了,有局限性。对单一对象中成员进行操作的多线程需要静态static关键字

下面是实现implements Runnable方法

package com.swift.duoxiancheng;

class Tickets implements Runnable {

    private int ticket = 1000;

    @Override
    public void run() {
        sell();
    }

    // 给带循环的方法加synchronized之后只有一个线程卖票,是因为锁定一个线程执行循环当然只有一个线程在卖票,应该把锁加在循环里边
    // 加在里边仍然有线程等待在循环外,最后出现负票数的情况,因为while之外也出现了同步,方法中不循环卖票,只卖一张票
    // while中写判断会影响结果,出现负票数
    public void sell() {
        while (true) {
            synchronized (this) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(0);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket--;
                    System.out.println(Thread.currentThread().getName() + "還有餘票:" + ticket);
                }
            }
        }
    }
}

public class SellTickets_Runnable {
    public static void main(String[] args) {
        Tickets t = new Tickets();

        Thread t1 = new Thread(t, "票窗口1");
        Thread t2 = new Thread(t, "票窗口2");
        Thread t3 = new Thread(t, "票窗口3");
        Thread t4 = new Thread(t, "票窗口4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        System.out.println("Hello World!");
    }
}

锁可以在方法上,也可以用同步代码块,同步代码块较好,可以局部锁

锁可以使对象synchronized(this) 也可以是字符串synchronized("锁")

加锁的时候注意,如果锁住的是一个循环,那就只有一个线程执行直到完成

package com.swift.duoxiancheng;

class Ticketz implements Runnable {

    private int ticket = 100;

    @Override
    public void run() {
        sell();

    }
    //加上synchronized之后只有一个线程卖票,锁定一个线程执行循环当然只有一个线程在卖票
    public synchronized void sell() {
        while (ticket > 0) {
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticket--;
            System.out.println(Thread.currentThread().getName() + "還有餘票:" + ticket);
        }
    }
}

public class SellTickets_OnlyOneThreadSell {
    public static void main(String[] args) {
        Ticketz t = new Ticketz();

        Thread t1 = new Thread(t, "票窗口1");
        Thread t2 = new Thread(t, "票窗口2");
        Thread t3 = new Thread(t, "票窗口3");
        Thread t4 = new Thread(t, "票窗口4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        System.out.println("Hello World!");
    }
}