哪个线程在并发线程中首先完成?

时间:2016-06-17 05:29:47

标签: java multithreading

我是java中并发线程的新手。我正在尝试编写一个简单的赛马模拟代码。

我想知道哪个线程先完成。
下面的代码抛出错误:不兼容的类型:线程无法转换为Gate

winner = (Gate)Thread.currentThread();

Gate.java

public class Gate implements Runnable{
    public String horseName;
    public final int GATE_DISTANCE = 20;
    public final int FINISH_LINE_DISTANCE = 100;
    public CyclicBarrier barrier;

    public Gate(CyclicBarrier barrier,String horseName){
        this.horseName = horseName;
        this.barrier = barrier;
    }

    public void run(){
        //Walk all horses to respective racing gates before starting race
        for(int distanceCovered = 0; distanceCovered < GATE_DISTANCE;){
            distanceCovered += gallop();
            int distanceLeft = GATE_DISTANCE - distanceCovered;
            if(distanceLeft < 0){
                distanceLeft = 0;               
            }
            System.out.println(horseName + "\t\tgate distance left " + distanceLeft);
            if(distanceLeft == 0){
                break;
            }
        }

        //Wait for all horses to be at racing gates
        try{
            barrier.await();
        }
        catch(InterruptedException ie){
            System.out.println("INTERRUPTED");
        }
        catch(BrokenBarrierException bbe){
            System.out.println("BROKEN");
        }

        //ACTUAL HORSE RACE
        for(int distanceCovered = 0; distanceCovered < FINISH_LINE_DISTANCE;){
            distanceCovered += gallop();
            int distanceLeft = FINISH_LINE_DISTANCE - distanceCovered;
            if(distanceLeft < 0){
                distanceLeft = 0;               
            }
            System.out.println(horseName + "\t\tgate distance left " + distanceLeft);
            if(distanceLeft == 0){
                break;
            }
        }   

        Main.done();
    }   

    public int gallop(){
        final int MIN_GALLOP = 1,
                        MAX_GALLOP = 10;

        Random random = new Random();   
        int gallopRange = MAX_GALLOP - MIN_GALLOP + 1;  
        int totalGallop = random.nextInt(gallopRange) + MIN_GALLOP; 
        return totalGallop;
    }   
}

GateMain.java

public class GateMain{
    private static Gate winner = null;


    public static void main(String[] args) {
        int horseCount = 5;

        List<String> horseNames = new ArrayList<String>();
        List<Thread> RG = new ArrayList<Thread>();

        horseNames.add("Red Bullet");
        horseNames.add("Green Furious");
        horseNames.add("Pink Mirage");
        horseNames.add("Blue Dash");
        horseNames.add("Yellow Burst");     

        Scanner scan = new Scanner(System.in);

        final CyclicBarrier cb = new CyclicBarrier(horseCount,new Runnable(){
            public void run(){
                System.out.print("\nALL HORSES ARE IN THEIR RESPECTIVE RACING GATES");
                System.out.println("\nRACE BEGIN!!!\n");
            }
        });

        for(int horseCtr = 0; horseCtr < horseCount; horseCtr++){
            Gate rg = new Gate(cb,horseNames.get(horseCtr));            
            Thread thread = new Thread(rg);
            thread.start();

            RG.add(thread);
        }

        for(Thread thread: RG){
            try{
                thread.join();
            }
            catch(InterruptedException ie){
                System.out.println("Thread Interrupted");
            }           
        }
        System.out.println(winner.horseName + "\t\t\twins!");
    }

    synchronized static void done(){
        if(winner == null){
            winner = (Gate)Thread.currentThread();
        }
    }
}

3 个答案:

答案 0 :(得分:2)

我会使用全局AtomicInteger

public static AtomicInteger finishLine = new AtomicInteger(0);

每匹马(线程)都应该有自己的place变量

int place;

当一匹马完成比赛时,它确定了自己的位置:

place = finishLine.incrementAndGet();

到达终点线的第一匹马将获得place=1,第二匹马,place=2,依此类推。然后,main()例程必须检查每匹马,找出哪一匹place=1。那将是胜利者。

这是一个不同的想法,受到越野足球赛终点线的启发:使用线程安全队列而不是AtomicInteger。

public static ArrayBlockingQueue<Horse> chute =
    new ArrayBlockingQueue<>(NUMBER_OF_HORSES);

当每匹马到达终点线时,它会进入滑槽。

chute.add(this);

这样,就没有必要明确等待比赛结束,也没有必要明确地对终结者进行排序:

Horse win = chute.take();    //waits for the first horse to finish
Horse place = chute.take();  //waits for the second horse
Horse show = chute.take();   //...

答案 1 :(得分:1)

然而,根据Java的规则,只是在这里进行同步是行不通的。您还必须同步您希望线程读取的更新。取决于变量是什么,可能是也可能不是问题。

您可能需要更多地考虑您的线程模型,并在此描述您想要做什么。如果您不了解互斥,则可能还没有准备好设计线程代码。

如果您尝试从静态成员访问实例字段,我不得不想知道如何编译代码。

Thread.currentThread()返回您(或其他库代码)创建的实际Thread对象。这可以是一个Gate线程,但这一切都取决于它运行的Thread对象。最安全的是首先使用instanceof进行检查。

答案 2 :(得分:0)

根据docs Thread.currentThread()返回对当前线程的引用,而不是对象。因此,您应该查找对象的引用,即this关键字。

您希望将winner作为私人会员。您无法从另一个类的run()更改它。因此,您可以将当前对象从run()作为参数传递给GateMainthis的方法。

您可以将done()方法编辑为:

synchronized static void done(Gate new_gate){
    if(winner == null){
        winner = new_gate;
    }
}

将行Main.done()替换为Main.done(this)