// Topic: Multithreading to write files
/**
There are four threads 1, 2, 3, 4. The function of thread 1 is to output A, the function of thread 2 is to output B, and so on...
There are now four files file1, file2, file3, file4. Initially empty.
Now let's make the four files look like this:
file1:A B C D A B....
file2:B C D A B C....
file3:C D A B C D....
file4:D A B C D A....
**/
My train of thought:
1. Each thread records the order in which it wants to write files, and starts from scratch after writing all files.
2. There is something similar to thread scheduling, where threads are executed in order, and then all threads are executed from scratch.
3. When each thread executes, it needs to update the file that it writes next time. If it is finished, it will start over again.
4. After each thread is executed, the next thread to be executed in the thread scheduling needs to be updated.
The following code is written in a sloppy manner, without any comments, and some unnecessary codes are not organized.
import java.io.FileWriter; import java.io.IOException; public class ThreadApp { public static void main(String[] args) { final Re r = new Re(); WriteTask t1 = new WriteTask(1, 1, "A", new int[] { 1, 4, 3, 2 }, r); WriteTask t2 = new WriteTask(2, 2, "B", new int[] { 2, 1, 3, 4 }, r); WriteTask t3 = new WriteTask(3, 3, "C", new int[] { 3, 2, 1, 4 }, r); WriteTask t4 = new WriteTask(4, 4, "D", new int[] { 4, 3, 2, 1 }, r); new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); new Thread(t4).start(); } } class Re { // thread id to write next public volatile int nextThread = 1; } class WriteTask implements Runnable { // 1 - file1 file4 file3 file2 // 2 - file2 file1 file3 file4 // 3 - file3 file2 file1 file4 // 4 - file4 file3 file2 file1 // private volatile boolean stop = false; private Re lock; // private final int id; private final String ch; private final int[] fileNos; private int currfileNos; public WriteTask(int id, int nextThread, String ch, int[] fileNos, Re lock) { this.id = id; this.ch = ch; this.fileNos = fileNos; this.lock = lock; } @Override public void run() { while (!stop) { synchronized (lock) { // If not equal, the current thread does not need to write to other threads while (id != lock.nextThread) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace (); } } if (currfileNos == 4) currfileNos = 0; FileWriter fw = null; try { fw = new FileWriter("file" + fileNos[currfileNos], true); fw.write(ch); if (++currfileNos > 3) currfileNos = 0; // reset if greater than 4 if (++lock.nextThread > 4) lock.nextThread = 1; } catch (IOException e) { e.printStackTrace (); stop = true; } finally { try { if (null != fw) fw.close(); } catch (IOException e) { e.printStackTrace (); } // wake up all threads lock.notifyAll(); } } } } }
The following is the improved code, much clearer than the above.
import java.io.FileWriter; import java.io.IOException; import java.util.concurrent.TimeUnit; public class ThreadApp { public static void main(String[] args) { final ThreadSchedule r = new ThreadSchedule(); WriteTask t1 = new WriteTask(1, "A", new int[] { 1, 4, 3, 2 }, r); WriteTask t2 = new WriteTask(2, "B", new int[] { 2, 1, 3, 4 }, r); WriteTask t3 = new WriteTask(3, "C", new int[] { 3, 2, 1, 4 }, r); WriteTask t4 = new WriteTask(4, "D", new int[] { 4, 3, 2, 1 }, r); new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); new Thread(t4).start(); } } /** * schedule thread */ class ThreadSchedule { public int willRunThreadId = 1; public final int threadCount = 4; } /** * write tasks */ class WriteTask implements Runnable { // 1 - file1 file4 file3 file2 // 2 - file2 file1 file3 file4 // 3 - file3 file2 file1 file4 // 4 - file4 file3 file2 file1 // private volatile boolean stop = false; private ThreadSchedule lock; // thread id private final int id; // characters to write private final String ch; // write the number of the file private final int[] fileNos; // total number of files private final int countFile = 4; // The number of the file currently being written private int currfileNo; public WriteTask(int id, String ch, int[] fileNos, ThreadSchedule lock) { this.id = id; this.ch = ch; this.fileNos = fileNos; this.lock = lock; } @Override public void run() { while (!stop) { synchronized (lock) { while (id != lock.willRunThreadId) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace (); } } FileWriter fw = null; try { System.out.println("thread" + id + " writing" + "file" + fileNos[currfileNo] + " "); TimeUnit.SECONDS.sleep(1); fw = new FileWriter("file" + fileNos[currfileNo], true); fw.write(ch); if (++currfileNo == countFile) currfileNo = 0; // reset if greater than 4 if (++lock.willRunThreadId > lock.threadCount) lock.willRunThreadId = 1; } catch (IOException e) { e.printStackTrace (); stop = true; } catch (InterruptedException e) { e.printStackTrace (); } finally { try { if (null != fw) fw.close(); } catch (IOException e) { e.printStackTrace (); } // wake up all threads lock.notifyAll(); } } } } }