我想在Java 5之前修改Java线程的基本原理,这样我就可以理解Java 5和更高版本的改进。
我从一个自定义集合开始,需要帮助:
kill变量的正确位置是哪个?它是在线程中还是在集合中,就像我做的那样?public class ThreadCreation {
public static void main(String[] args) {
MyCollection coll = new MyCollection();
coll.kill = false;
RemoveCollClass t2 = new RemoveCollClass();
t2.setName("Thread2");
t2.coll = coll;
t2.start();
AddCollClass t1 = new AddCollClass();
t1.setName("Thread1");
t1.coll = coll;
t1.start();
RemoveCollClass t3 = new RemoveCollClass();
t3.setName("Thread3");
t3.coll = coll;
t3.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
coll.kill = true;
}
static class AddCollClass extends Thread {
volatile MyCollection coll;
int count = 0;
@Override
public void run() {
while (!coll.kill) {
System.out.println(Thread.currentThread().getName()
+ " --> AddCollClass Attempt -->" + count);
coll.add();
count++;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
static class RemoveCollClass extends Thread {
volatile MyCollection coll;
int count = 0;
@Override
public void run() {
// System.out.println("ThreadClass is running ");
while (!coll.kill) {
System.out.println(Thread.currentThread().getName()
+ " -->RemoveCollClass Attempt -->" + count);
coll.remove();
count++;
}
}
}
static class MyCollection {
Stack<String> container = new Stack<String>();
int maxSize = 5;
volatile boolean kill = false;
public synchronized boolean isFull() {
if (container.size() >= maxSize)
return true;
else
return false;
}
public synchronized boolean isEmpty() {
if (container.size() <= 0)
return true;
else
return false;
}
public synchronized void add() {
if (isFull()) {
try {
System.out.println("wait triggered on-->"
+ Thread.currentThread().getName());
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
notify();
}
}
if (!isFull()) {
container.add(Thread.currentThread().getName());
System.out.println(" Add Completed by "
+ Thread.currentThread().getName());
notify();
}
}
public synchronized void remove() {
if (isEmpty()) {
try {
System.out.println("wait triggered on-->"
+ Thread.currentThread().getName());
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
notify();
}
}
if (!isEmpty()) {
container.pop();
System.out.println(" Remove Completed by "
+ Thread.currentThread().getName());
}
}
}
}发布于 2014-04-13 03:54:20
不管您使用的是哪个版本的Java,在Java中使用最佳实践线程时,有几件事情是“错误的”。
通过同步这些方法,这意味着任何人都可以破坏您的程序。如果一个人决定在他们的程序中使用您的类作为某种构造,那么他们会:
private final MyCollection mycoll = new MyCollection();
public void methodABC() {
synchronized(mycoll) {
// do a bunch of stuff
}
}突然你的同步结束了..。死锁就会发生。见这个堆栈溢出的讨论。
既然您的MyCollection类有collection堆栈实例,请使用它作为监视器锁……(并让它成为私人决赛:
static class MyCollection {
private final Stack<String> container = new Stack<String>();
int maxSize = 5;
volatile boolean kill = false;
public boolean isFull() {
synchronized (container) {
return container.size() >= maxSize;
}
}另外,您应该使用notifyAll(),而不仅仅是notify()。尤其是当您使用方法/实例同步时,因为您类之外的任何人都可能得到通知,如果他们阻止您的类.您可能最终会通知其他不属于您类的线程.实际上,那里有一个真正的bug:
如果两个线程从一个完整的集合中移除一个项,而另外两个线程正在等待空间将其放入.然后两个移除线程都可以通知相同的添加线程,而第二个添加线程可能仍然在等待,即使通过有空间.
使用notifyAll();
在Java5被打破之前是不稳定的。不要用它。
在持有锁时,您的任何方法都不会阻塞(它们都是释放锁的“等待”)。因此,你的锁保持时间真的很短。
因此,没有理由将kill分离为易失性。只需有一个kill和isKilled方法。
当使用你可以理解这篇文章时,可以使用易失性
所有的“线程”类都应该是可运行的。
它们应该有私有的最终变量,而根本不具有易失性。例如,这个类:
静态类RemoveCollClass扩展线程{易失性MyCollection coll;int count = 0;@Override (){ // System.out.println("ThreadClass正在运行");而(!coll.kill) {ThreadClass+ -->RemoveCollClass尝试->“+count”;coll.remove();count++;}}
看起来应该是:
static class RemoveCollClass implements Runnable {
private final MyCollection coll;
int count = 0;
public RemoveCollClass(MyCollection coll) {
super();
this.coll = coll;
}
public void run() {
// System.out.println("ThreadClass is running ");
while (!coll.isKilled()) {
System.out.println(Thread.currentThread().getName()
+ " -->RemoveCollClass Attempt -->" + count);
coll.remove();
count++;
}
}
}然后,使用Runnable作为线程构造函数:
RemoveCollClass rcc2 = new RemoveCollClass(coll);
Thread t2 = new Thread(rcc2, "Thread2");
t2.setDaemon(true);
t2.start();小事情:
} catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); notify(); } - Don't use i-liner if/else blocks. They lead to bugs: if (container.size() <= 0) return true; https://codereview.stackexchange.com/questions/47030
复制相似问题