【问题标题】:Java Multithreading two classes in mainJava多线程在main中的两个类
【发布时间】:2020-09-18 20:08:06
【问题描述】:

我对编程很陌生,我正在尝试编写一个带有TimerChecksUserInput 类的Java 程序,如下所示。如何让它们在主类中同时运行?

我在打印ChecksUserInput 中的字长时也遇到了问题。

main.java:

package application;

public class Main {
    public static void main(String[] args) {
        CreateBoard board = new CreateBoard();
        board.run();

        Timer timer = new Timer();
        timer.run();

        ChecksUserInput input = new ChecksUserInput();
        input.run();
    }
}

timer.java:

package application;

public class Timer {
    private static void time() {
        final int mili = 1000;
        final int sec = 60;
        final int oneMinute = (mili * sec);

        System.out.println("Start 3 minute timer");
        sleep(oneMinute * 2);

        System.out.println("One minute remaining...");
        sleep(oneMinute);

        System.out.println("Time's up!");
    }

    private static void sleep(int sleepTime) {
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        time();
    }
}

checksuserinput.java:

package application;

import java.util.*;

public class ChecksUserInput {
    private static String UserInput() {
        Scanner sc = new Scanner(System.in);
        System.out.println("Begin entering words!");

        String word = null;
        for (int i = 0; i < 10000; i++) {
            word = sc.nextLine();
        }

        return word;
    }

    private static int length(String word) {
        int wordLength = word.length();
        return wordLength;
    }

    public void run() {
        String userWord = UserInput();
        int wordLength = length(userWord);
        System.out.println(wordLength);
    }
}

【问题讨论】:

    标签: java multithreading synchronize


    【解决方案1】:

    Java 中多线程的基础是 Thread 类。使用的一般结构是:

    Thread newProcess = new Thread(processToRun); //Create a thread which will execute the process
    newProcess.setDaemon(true/false); //when false, the thread will keep the JVM alive beyond completion of 'main'
    newProcess.start(); //Start processToRun in a new thread
    

    要启动几个独立的进程,这应该足够了。例如,以下启动 10 个线程,每个线程将打印循环中的索引。最后,进程休眠 5 毫秒,因为生成的线程是守护进程。删除它可能会导致进程在打印任何消息之前终止。

        public static void main(String args[]) throws Exception
        {
            for(int i = 0; i < 10; i++) { int index = i; start(() -> System.out.println(index)); }
            Thread.sleep(5);
        }
    
        public static void start(Runnable processToRun)
        {
            Thread newProcess = new Thread(processToRun);
            newProcess.setDaemon(true);
            newProcess.start();
        }
    

    除此之外,问题开始变得更加复杂/上下文相关。例如:

    1. 在 2 个线程中运行的进程如何相互通信?
    2. 在 2 个线程中运行的进程如何访问/修改它们之间的公共状态?

    在创建简单游戏的情况下,一种选择是使用队列将用户输入提供给游戏,并在单个线程中更新游戏进程。以下示例在主线程上侦听用户输入命令(上、下、左、右)并将有效命令添加到队列中。在不同的线程中轮询和处理有效命令以更新板上的位置。

    示例:

        public static void main(String args[])
        {
            Board board = new Board();
            BlockingQueue<Move> movesQueue = new ArrayBlockingQueue<>(100);
            Scanner systemListener = new Scanner(System.in);
            start(() -> routeBoardMovesToQueue(board, movesQueue)); /*route moves from the queue to the board in a new thread*/
            while(true)
            {
                Optional<Move> nextMove = Move.resolve(systemListener.nextLine());
                if(nextMove.isPresent())
                    movesQueue.offer(nextMove.get()); /*Write moves from System.in to the queue*/
                else
                    System.out.println("Invalid Move Provided");
            }
        }
        
        public static void routeBoardMovesToQueue(Board board, BlockingQueue<Move> movesQueue)
        {
            try
            {
                while(true)
                {
                    Move next = movesQueue.poll(100_000, TimeUnit.DAYS);
                    if(next != null) board.performMove(next);
                }
            }
            catch(InterruptedException ignored){ System.out.println("Stopping"); }
        }
    
        public static void start(Runnable processToRun)
        {
            Thread newProcess = new Thread(processToRun);
            newProcess.setDaemon(true);
            newProcess.start();
        }
    
        public static final class Board
        {
            private final Location location;
            public Board(){ this.location = new Location(); }
            public void performMove(Move move)
            {
                switch(move)
                {
                    case Up:    location.y += 1; break;
                    case Down:  location.y -= 1; break;
                    case Right: location.x += 1; break;
                    case Left:  location.x -= 1; break;
                }
                System.out.println("New Position: (" + location.x + ", " + location.y + ")");
            }
    
            public static class Location{ int x = 0; int y = 0; }
        }
    
        public enum Move
        {
            Up, Down, Left, Right;
            public static Optional<Move> resolve(String move){ return Stream.of(Move.values()).filter(mv -> Objects.equals(move, mv.name())).findAny(); }
        }
    

    【讨论】:

      【解决方案2】:

      您应该在您最喜欢的搜索引擎上搜索“java multithreading”并将您的代码与这些示例进行比较

      您会发现这些人(大部分)在他们的类上实现了 Runnable 接口。 所以

      -- 公共类 ChecksUserInput {

      ++ 公共类 ChecksUserInput 实现 Runnable{

      而 run() 是该接口的一个方法,他们必须实现。

      您的版本首先运行第一个类的 run 方法,然后是另一个。 但是当你实现runnable接口时,两个run方法会一个接一个地被调用,而不是等待第一个完成

      您应该自行搜索并找到更多示例,或者如果您遇到任何其他问题,请查看多线程文档

      【讨论】:

      • 我有,但我不太了解多线程,所以我希望能得到一点帮助我现在真的只编程了几个月,我不知道我是否足够先进获得多线程的水平,但感谢您的帮助,我将尝试从这里开始
      【解决方案3】:

      所以在@BATIKAN BORA ORMANCI 和@mike1234569 给了我这个链接https://www.geeksforgeeks.org/multithreading-in-java/ 之后,我真的能够弄清楚了

      打包应用程序;

      公共类主{

      public static void main(String[] args) {
      
          CreateBoard board = new CreateBoard();
          board.run();
      
          Thread timer = new Thread(new Timer());
          Thread input = new Thread(new ChecksUserInput());
      
          timer.start();
          input.start();
      
          try {
              timer.join();
              input.join();
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
      

      }

      我设置我的类以按照 Batikan 的建议实现 Runnable

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-05
        • 2023-03-08
        • 1970-01-01
        • 2013-11-21
        • 2012-10-23
        • 1970-01-01
        • 2012-11-03
        • 2013-11-12
        相关资源
        最近更新 更多