在Java中使用多线程以适当的顺序从两个文件中读取行

在Java中使用多线程以适当的顺序从两个文件中读取行,java,multithreading,file-handling,Java,Multithreading,File Handling,假设我有两个文件名A和B。如果 文件A包含: 嗨 你好吗 文件B包含: 我叫阿尤什 我做得很好 输出: 嗨 我叫阿尤什 你好吗 我做得很好 正如我所知,我们只能请求JVM,如果队列中的另一个线程没有准备好,那么下一个线程将再次执行。我尝试过使用标志和设置优先级,但我总是得到随机输出。有时第二个文件B中的行是先读取的,有时是从文件A中读取的。这扰乱了我想要答案的顺序 import java.io.*; import java.util.*; class Synchronization{ p

假设我有两个文件名A和B。如果

文件A包含:

你好吗

文件B包含:

我叫阿尤什

我做得很好

输出:

我叫阿尤什

你好吗

我做得很好

正如我所知,我们只能请求JVM,如果队列中的另一个线程没有准备好,那么下一个线程将再次执行。我尝试过使用标志和设置优先级,但我总是得到随机输出。有时第二个文件B中的行是先读取的,有时是从文件A中读取的。这扰乱了我想要答案的顺序

import java.io.*;
import java.util.*;
class Synchronization{
    public void readFromFile(Scanner sc) throws Exception{
        while(sc.hasNext()){
            System.out.println(sc.nextLine());
            Thread.sleep(500);
        }
     }
  }

class SynchronizedThreads extends Thread{

    @Override
    public void run(){
        Scanner sc;

        if(Thread.currentThread().getName().equals("A")){
            try{
                sc = new Scanner(new File("FirstFile.txt"));
                object.readFromFile(sc);
            }catch(Exception ex){
                System.out.println(ex);
            }
        }else if(Thread.currentThread().getName().equals("B")){
            try{
                sc = new Scanner(new File("SecondFile.txt"));
                object.readFromFile(sc);
            }catch(Exception ex){
                System.out.println(ex);
            }
        }
    }

   public static void main(String[] args) {
      Synchronization object = new Synchronization();
      SynchronizedThreads t1 = new SynchronizedThreads(object);
      SynchronizedThreads t2 = new SynchronizedThreads(object);
      //SynchronizedThreads t = new SynchronizedThreads(object);
      t1.setName("A");
      t2.setName("B");
      //t.setName("Temp");
      //t.start();
      //t1.setPriority(10);
      //t2.setPriority(5);
      t1.start();
      t2.start();
   }
}
第二个代码

import java.util.*;
import java.io.*;
class ConcurrencyControl extends Thread{

    volatile static boolean sema = true;
    private String pathForFirstFile = "FirstFile.txt";
    private String pathForSecondFile = "SecondFile.txt";

    @Override//run() Method
    public void run(){
        String  threadName = Thread.currentThread().getName();
        if(threadName.equals("FirstFile")){
            try{
                Scanner sc = new Scanner(new File(pathForFirstFile));
                if(sema == true){ 
                    while(sc.hasNextLine() /*&& sema == true*/){
                        System.out.println(sc.nextLine());
                        sema = false;
                        sleep(500);
                    }
                }else{
                    sleep(500);
                }
            }catch(Exception ex){
                    System.out.println(ex);
                }
            }
        else if(threadName.equals("SecondFile")){
            try{
                Scanner sc1 = new Scanner(new File(pathForSecondFile));
                if(sema == false){
                    while(sc1.hasNextLine() /*&& sema == false*/){
                        System.out.println(sc1.nextLine());
                        sema = true;
                        sleep(500);
                    }
                }else{
                    sleep(500);
                }
            }catch(Exception ex){
                System.out.println(ex);
            }
        }
    }

    public static void main(String[] args){
        ConcurrencyControl threadOne = new ConcurrencyControl();
        threadOne.setName("FirstFile");
        ConcurrencyControl threadSecond = new ConcurrencyControl();
        threadSecond.setName("SecondFile");
        threadOne.start();
        threadSecond.start();
    }
}

让一个标志显示
isATurn
。最初将
i设置为
true
。按顺序创建两个线程调用。将条件语句放入
synchronized
块中,以检查回合数并相应地处理它。每次处理文件时都必须反转该标志

public void processA() {
   while (!isATurn); //wait till processB method to invert the flag
   synchronized(this) {
       processNow();
       isATurn = !isATurn;  
   }
}
以相同的方式实现
processB
方法

编辑:
Thread.sleep()
的级别稍低,使用它实现线程安全性比较困难。Java为我们提供了
synchronized
关键字,以更优雅的方式处理这些问题


编辑:在
synchronized
块外忙着等待,以避免CPU利用率低。

同步应该怎么做?正如我看到的,你同时开始读取文件,并立即输出内容,而不需要等待任何东西(除了半秒的睡眠,但这是无条件的)。我不是这方面的专家,但它看起来像生产者/消费者,两个生产者给一个消费者。消费者将需要控制订单things@skandigraun该类只有一个我在SynchronizedThreads中调用的方法。实际上,我需要一个sleep方法,因为如果线程a从第一个文件中读取第一行,它应该等待线程B从第二个文件中读取第一行,并且应该保持顺序。我有点明白这个想法,但是这个方法总是随机和不可靠的,因为它依赖于运气。您可以引入一个锁或标志来指示何时可以读取文件。当A完成一行时,它将标志设置为“B_can_read”,然后进入睡眠状态,直到标志为“A_can_read”。B也是这样做的:如果标志是“B_can_read”,它会读取,并将标志设置为“A_can_read”,然后进入睡眠状态,等待轮到它。或者类似的东西,作为一个例子,我试着用这个逻辑。我正在编辑并发布第二个代码,请检查您是否可以在那里提供帮助。谢谢@skandigraun
,而(!isATurn)
-这被称为。它有两个好处:1)非常低的延迟编程,2)创建风扇加热器。在这两个选项中,有一点需要注意,就是你已经将一个线程提升到100%,其他任何东西都无法使用它。这是一个非常糟糕的主意。我同意@Boristeider的观点,这个问题本身强加了一些秩序。如果任务是独立的,那么我们可以通过线程提高CPU利用率。我相信这种固有的命令强加总是会导致CPU利用率低下。欢迎您就如何提高效率提出建议。不正确。例如,使用
wait()
notify()
将允许等待线程返回到调度程序。如果您不知道如何编写并发代码,请不要发布答案。