// 题目: 多线程写文件
/**
有四个线程1、2、3、4。线程1的功能就是输出A,线程2的功能就是输出B,以此类推.........
现在有四个文件file1,file2,file3, file4。初始都为空。
现要让四个文件呈如下格式:
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....
**/
我的思路:
1.每个线程记录自己要写入文件的顺序,写完一遍所有文件以后又从头来。
2.有个类似线程调度的东西,这里面按顺序执行线程,执行完所有线程以后又从头来。
3.每个线程执行的时候,要更新自己下一次写入的文件,如果写完一遍又从头来。
4.每个线程执行完以后,需要更新线程调度里面下一个要执行的线程。
下面的代码,写的比较潦草,也没有写什么注释,有些不必要的代码也没有整理。
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 {
// 下一个写入的线程id
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) {
// 如果不相等 表示当前线程不需要写入 让给其他线程
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;
// 如果大于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();
}
// 唤醒所有的线程
lock.notifyAll();
}
}
}
}
}
下面的是改进的代码,比上面的清楚很多了。
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();
}
}
/**
* 调度线程
*/
class ThreadSchedule {
public int willRunThreadId = 1;
public final int threadCount = 4;
}
/**
* 写任务
*/
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;
// 线程id
private final int id;
// 写入的字符
private final String ch;
// 写入文件的编号
private final int[] fileNos;
// 总文件数
private final int countFile = 4;
// 当前正要写入的文件编号
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("线程 " + id + " 正在写入 " +"file" + fileNos[currfileNo] + " ");
TimeUnit.SECONDS.sleep(1);
fw = new FileWriter("file" + fileNos[currfileNo], true);
fw.write(ch);
if (++currfileNo == countFile)
currfileNo = 0;
// 如果大于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();
}
// 唤醒所有的线程
lock.notifyAll();
}
}
}
}
}