Java多线程基础求指点

kong_resty 发布于 2014/03/11 16:41
阅读 1K+
收藏 2
package concurrent001;


public class BuyTicket extends Thread {

    private int tickets;
    
    private String sellName = "";
    
    public BuyTicket(int num){
        this.tickets = num;
    }
    
    @Override
    public void run() {
            while (tickets> 0) {
                 buyTicket(); 
            }
    }
    
    
    public synchronized void buyTicket(){
        if(tickets>0){
            System.out.println(Thread.currentThread().getName() + "售出了" + tickets + "号票子");
            tickets--;
        }
    }
    
    
    
    public static void main(String[] args) throws InterruptedException {
        BuyTicket bt = new BuyTicket(20);
        Thread t1 = new Thread(bt);
        Thread t2 = new Thread(bt);
        Thread t3 = new Thread(bt);
        t1.start();
        t2.start();
        t3.start();
        t1.join();t2.join();t3.join();
        System.out.println("end................");
        
    }

}

执行结果

Thread-1售出了20号票子
Thread-1售出了19号票子
Thread-1售出了18号票子
Thread-1售出了17号票子
Thread-1售出了16号票子
Thread-1售出了15号票子
Thread-1售出了14号票子
Thread-1售出了13号票子
Thread-1售出了12号票子
Thread-1售出了11号票子
Thread-1售出了10号票子
Thread-1售出了9号票子
Thread-1售出了8号票子
Thread-1售出了7号票子
Thread-1售出了6号票子
Thread-1售出了5号票子
Thread-1售出了4号票子
Thread-1售出了3号票子
Thread-1售出了2号票子
Thread-1售出了1号票子
end................
我预期的是  3个线程分别执行  现在为什么只有一个线程在执行? 什么情况?










加载中
1
我不说话
我不说话

synchronized 这个基本是把锁交给等待时间最短的线程,你明白吗?

你用Reentrantlock 肯定就没问题,他会把锁交给等待时间最长的线程。

你可以试一下……

我又试了一下,是你的票太少了。第二个线程启动的时候,第一个线程基本都把票卖光了

NealFeng
NealFeng
最好能指出结论引用自那里。我理解,锁释放后怎么切换到等待该锁的其它进程这个和JVM的具体实现有关。从ReentrantLock的API文档中看,创建锁时指定fair参数为true才会favor(倾向于)分配给等待时间最长得线程,也不是“必须”分配给该线程。
1
王涛
王涛

跟什么锁对象啊,锁方法之类的没有任何关系

完完全全就是CPU切换线程的事,楼主可以试着把票子改成几万或者几十万张就可以看到效果了

王涛
王涛
回复 @章彦儿 : 照你这么说,这事真的很诡异
kong_resty
kong_resty
是不是和机器也有关系啊 我这边数据量 改到很大都是一个线程在执行 我也猜是cpu切换线程的原因
1
巴顿
巴顿

原封不动用楼主代码,但是tickets改为1000,结果如下

Thread-1售出了1000号票子
Thread-2售出了999号票子
Thread-3售出了998号票子
Thread-1售出了997号票子
Thread-2售出了996号票子
Thread-3售出了995号票子
Thread-1售出了994号票子
Thread-2售出了993号票子
Thread-3售出了992号票子
Thread-1售出了991号票子
Thread-2售出了990号票子
Thread-3售出了989号票子
Thread-1售出了988号票子
Thread-2售出了987号票子
Thread-3售出了986号票子
Thread-1售出了985号票子
Thread-2售出了984号票子
Thread-3售出了983号票子
。。。。。。



所以说楼主代码应该是没问题的。只不过和cpu分配有关。

一般为了防止这样的情况出现,可以加sleep或者提高数量。

楼上有些人说线程锁方法有问题,这个应该不是吧。给方法加锁,也就是锁住了这个方法里面的BuyTicket实例,而且现在3个线程都使用了这个实例,所以假如线程1拿到了这个锁,那么线程2就要等待线程1执行完。加锁作用应该就是这个。


愚见,欢迎使劲拍砖!

0
Brin想写程序
Brin想写程序

synchronized 用错了。synchronized 锁住了这个对象对buyTicket的调用。

不理解synchronized 的情况下,不要用synchronized 锁方法,要锁块。


0
zjxzjx
zjxzjx
因为第一个线程持有了锁,其他线程进不去 buyTicket
0
公孙二狗
公孙二狗
t1.join();t2.join();t3.join(); 问题在这
0
zjxzjx
zjxzjx
public  void buyTicket() throws InterruptedException{
    	synchronized (this) {
    		while(tickets>0){
    			this.notifyAll();
    			  System.out.println(Thread.currentThread().getName() + "售出了" + tickets + "号票子");
    	            tickets--;
    	        	this.wait();
			}
		
		}
    
     
    }



甘薯
甘薯
回复 @zjxzjx : 楼主在第一楼就已经告诉别人不要告诉他用sleep方法。。。
zjxzjx
zjxzjx
回复 @章彦儿 : 你可以理解为cpu切换线程需要一点点时间..所以你在while里面sleep一会 时间就够cpu切过去了.
kong_resty
kong_resty
回复 @zjxzjx : 能够讲讲cup是怎么切换线程的就更加好了 为什么会切换不到其他线程
zjxzjx
zjxzjx
回复 @章彦儿 : 循环里每次执行完就 Thread.sleep(1000); 也可以.
zjxzjx
zjxzjx
回复 @章彦儿 : 其实这里不是锁的问题,因为锁在buyTicket执行完后就释放了.. 是因为在第一个线程执行完第一次buyTicket时,cpu还没切换到其他线程时,第二次循环就又来又给占了..
下一页
0
凤城回忆
凤城回忆

synchronized 声明在方法上,表示线程拿到的锁是当前的对象,也就是BuyTicket bt = new BuyTicket(20);

你的run方法中使用while,bt对象的锁由Thread t1一直持有,所以t2、t3都没获得bt对象的锁,无法执行。

0
专业打酱油
专业打酱油

首先,你得知道,2,3线程肯定执行了的。

其次,你是单核CPU么。。。还是换机器吧。。

再次,虽然代码有点问题,不过还是不应该只看到t1。。。除非你真的是单核。。。






专业打酱油
专业打酱油
回复 @梅公子 : 哪忽悠了?
一号男嘉宾
一号男嘉宾
大哥,你真能忽悠,很明显是synchronized 锁住了方法的问题。
kong_resty
kong_resty
四核的机器
0
周志强
周志强
只有一个售票窗口,而且这个窗口只有20张票; t1,t2,t3 3个售票员排班上班售票;t1那个售票员比较勤快把票全卖完了,t2,t3就不用卖票了,然后3个售票员高高兴兴的下班了!
Romen
Romen
这个比如好精辟
返回顶部
顶部