@XQF
2016-12-22T22:24:43.000000Z
字数 3026
阅读 1099
java作业
把每个哲学家当作一个线程,筷子就是哲学家之间需要处理的共享资源。这里共享资源筷子设置为公用数组的形式。给每个哲学家线程标记(编号)与数组中的内容相匹配。于是将数组对象的使用设为同步,只能一个线程获得锁,并且要是其中一只筷子正在被另一个线程使用的话等待释放就可以了。这个哲学家(线程)使用结束后释放共享资源。
/**
* Created by XQF on 2016/12/18.
*/
class Philosopher extends Thread {
private String name;
private Fork fork;
public Philosopher(String name, Fork fork) {
super(name);
this.name = name;
this.fork = fork;
}
public void run() {
while (true) {
thinking();
fork.takeFork();
eating();
fork.putFork();
}
}
public void eating() {
System.out.println("I am Eating:" + name);
try {
sleep(1000);//模拟吃饭,占用一段时间资源
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void thinking() {
System.out.println("I am Thinking:" + name);
try {
sleep(1000);//模拟思考
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Fork {
/*5只筷子,初始为都未被用*/
private boolean[] used = {false, false, false, false, false, false};
/*只有当左右手的筷子都未被使用时,才允许获取筷子,且必须同时获取左右手筷子*/
public synchronized void takeFork() {
String name = Thread.currentThread().getName();
int i = Integer.parseInt(name);
while (used[i] || used[(i + 1) % 5]) {
try {
wait();//如果左右手有一只正被使用,等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
used[i] = true;
used[(i + 1) % 5] = true;
}
/*必须同时释放左右手的筷子*/
public synchronized void putFork() {
String name = Thread.currentThread().getName();
int i = Integer.parseInt(name);
used[i] = false;
used[(i + 1) % 5] = false;
notifyAll();//唤醒其他线程
}
}
//测试
public class ThreadTest {
public static void main(String[] args) {
Fork fork = new Fork();
new Philosopher("0", fork).start();
new Philosopher("1", fork).start();
new Philosopher("2", fork).start();
new Philosopher("3", fork).start();
new Philosopher("4", fork).start();
}
多线程一定共享资源,至于这个资源是通过直接同步还是通过同步方法的形式就是根据实际情况来判断了。
因为涉及到多线程,所以我使用同步加锁的方式使用单例模式。经常性的动作就是私有化构造方法,再自己写一个静态方法来获取对象实例。获取的时候判断环境中是不是已经有了这样的实例,要是已经有了就直接使用不用创建实例了,要是没有就直接创建实例。
/**
* Created by XQF on 2016/12/18.
*/
//任务类,给线程指定的动作就是写入日志
class MyTask implements Runnable {
private Logger logger;
private String string;
public MyTask(String string) {
logger = Logger.getLogger();
this.string = string;
}
@Override
public void run() {
logger.writeToLogFile(string);
}
}
public class Logger {
private static Logger logger;
private RandomAccessFile loggerFile;
private Logger() {
try {
//使用随机文件的方法写入
this.loggerFile = new RandomAccessFile("D:\\logger.txt", "rw");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static synchronized Logger getLogger() {
if (logger == null) {
logger = new Logger();
}
return logger;
}
public void writeToLogFile(String string) {
try {
loggerFile.seek(loggerFile.length());
// loggerFile.writeUTF(string);
loggerFile.write(string.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//唯一的实例
Logger logger = Logger.getLogger();
String string = "20162213202020---写入";
// String s = new String(string.getBytes(), "utf-8");
logger.writeToLogFile(string);
for (int i = 0; i < 3; i++) {
try {
Random random = new Random(47);
int a = random.nextInt(1000);
Thread.sleep(a);
new Thread(new MyTask("this is the No" + i + " thread!\n")).start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
使用随机文件写入的时候要将字符串转为byte,否则会出现乱码。