如何在多线程程序

时间:2017-06-09 18:32:33

标签: java multithreading synchronization

我是Java的初学者,我正在尝试创建一个程序,其中有两个小船"使用多线程在屏幕上互相竞争。我得到了线程部分,可以使两条线在屏幕上相互平行工作。

但是我希望线程在命令的同时启动,所以我找到了CountDownLatch类。我真的不太了解它,但我还是尝试使用它仍然使用一个锁存器,然后让线程等待()直到我调用latch.countDown()。这一切都运行良好,但我想知道哪个线程首先完成,所以我在main方法中使用了一个计时器和一个if语句来确定哪个线程/" boat"更快。

然而,我的两个问题是a。由于某种原因,所有内容都打印两次,就像它执行run()两次,以及b。 if语句总是直接转向其他语句,因为它并不认为记录的时间比另一个大。我感觉所有这一切都是由于我使用CountDownLatch造成的一些混乱,但我只是没有经验来解决它。

主要方法:

package practice;

import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.*;

public class Regatta {
    public static void main(String[] args) {
        Q timed = new Q();
        CountDownLatch latch = new CountDownLatch(0);
        Thread t1 = Thread.currentThread();
        Scanner scan = new Scanner(System.in);
        System.out.println("What team is rower 1 on?");
        String roweronename = scan.nextLine();
        System.out.println("What team is rower 2 on?");
        String rowertwoname = scan.nextLine();

        Rower r1 = new Rower(latch, roweronename, timed);
        Team2 r2 = new Team2(latch, rowertwoname, timed);

        try {
            System.out.println("ATTENTION");
            t1.sleep(1000);
            System.out.println("READY");
            t1.sleep(1000);
            System.out.println("ROW!");
            System.out.println();
            System.out.println(roweronename.toUpperCase() + "             " + rowertwoname.toUpperCase());
            System.out.println("--------------------------------------------");
            new Thread(r1).start();
            new Thread(r2).start();
            latch.countDown();

        } catch (InterruptedException e) {
            System.out.println("There was an error. Don't click out of the program.");
        } catch (Exception e) {
            System.out.println("There was another error");
        }
        try {
            r1.t.join();
            r2.t.join();
        } catch (InterruptedException e) {
            System.out.println("interruption error occurred");
        }
        double finalTimeOne = r1.finalTime;
        double finalTimeTwo = r2.finalTime;

        if (finalTimeOne < finalTimeTwo) {
            System.out.println(roweronename.toUpperCase() + " HAS WON THE RACE!");
        } else if (finalTimeTwo < finalTimeOne) {
            System.out.println(rowertwoname.toUpperCase() + " HAS WON THE RACE!");
        } else
            System.out.println("Nobody won");
    }
}
带有thread1的

子类:

package practice;

import java.util.concurrent.CountDownLatch;

public class Rower implements Runnable {
    int meters = 2000;
    double startTime, endTime, finalTime;
    Thread t;
    String name;
    CountDownLatch latch;
    Q timed;
    public Rower(CountDownLatch latch, String name, Q timed) {
        this.timed=timed;
        this.latch = latch;
        this.name = name;
        t = new Thread(this, name);
        t.start();
        System.out.println();   
    }

    public void run() {
        try {
            latch.await();
            double startTime = System.nanoTime();
            for (int i = 20; i >= 0; i--) {
                System.out.println("|");// each - is 10 meters
                Thread.sleep(100);
        }
            double endTime = System.nanoTime();
            double finalTime = endTime - startTime;
            timed.getTime(finalTime,name);

        } catch (InterruptedException e) {
            System.out.println("GET OUT THE WAY!");
            System.out.println("race postponed to tommorow");
        }

    }

}
带有线程2的

子类:

package practice;
import java.util.concurrent.CountDownLatch;

public class Team2 implements Runnable {
    Q timed=new Q();
    int meters = 2000;
    double startTime,endTime,finalTime;
    Thread t;
    String name;
    CountDownLatch latch;
    public Team2(CountDownLatch latch,String name, Q timed) {
        this.timed=timed;
        this.latch=latch;
        this.name = name;
        t = new Thread(this, name);
        t.start();
        System.out.println();
    }

    public void run() {
        try {

            latch.await();
            double startTime=System.nanoTime();

            for (int i = 20; i >= 0; i--) {
                int j=20-i;
                System.out.println("                  |");// each | is 10 meters
                Thread.sleep(100);
            }
            double endTime=System.nanoTime();
            double finalTime=endTime-startTime;

                timed.getTime(finalTime, name);


        } catch (InterruptedException e) {
            System.out.println("GET OUT THE WAY!");
            System.out.println("race postponed to tommorow");
        }

    }

}

使用synchronized方法获取完成时间的类:

  package practice;    
   public class Q {
    double finalTime;
    String name;
    synchronized void getTime(double finalTime, String name){
        this.finalTime=finalTime;
        this.name=name;
        System.out.println("Time of team "+this.name+": "+this.finalTime);//prints twice?
        System.out.println("vinay");
    }
}

1 个答案:

答案 0 :(得分:0)

在Rower(和Team2)类构造函数中,您正在初始化一个全新的Thread,并启动它:

public Rower(CountDownLatch latch, String name, Q timed) {
    this.timed=timed;
    this.latch = latch;
    this.name = name;
    //vvvvvvvv THIS IS THE PROBLEM vvvvvvvv//
    t = new Thread(this, name);
    t.start();
    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//
    System.out.println();   
}

Rower(或Team2)中不需要线程。在Regatta类中创建的线程足以调用Rower(和Team2)中的“run”方法

// These are all you need to get the boats to race!
new Thread(r1).start();
new Thread(r2).start();

另外,作为旁注:您根本不需要Team2课程......您应该能够通过初始化两个Rower对象来比赛两个不同的船只。

Rower r1 = new Rower(latch, roweronename, timed);
// Changed from Team2 to Rower
Rower r2 = new Rower(latch, rowertwoname, timed);

如果两艘船具有不同的功能,你只需要有两种不同的船级别,例如一艘船的推进力与另一艘不同(划船与帆船,摩托艇等)。在您的情况下,它们看起来基本相同(几乎是复制粘贴)。