我正在尝试为实验室编写一些程序,该实验室基本上是一个将数据存储在文件夹中的网络缓存,因此如果客户端想要打开网页,如果该页面不存在,该页面将存储在缓存文件夹中,并且它将显示给客户。我能够下载和显示页面,但是当线程必须等待时出现问题,因为请求的资源正在被下载并存储在缓存文件夹中。
下载类如下:
public class Downloads {
private ArrayList<DownloadsNode> nodes;
private int debug,readersCount=0,writersCount=0;
private Lock readLock=new ReentrantReadWriteLock().readLock();
private Lock writeLock=new ReentrantReadWriteLock().writeLock();
public Downloads ( int debug )
{ nodes = new ArrayList<DownloadsNode>();
this.debug = debug;
}
public synchronized DownloadsNode findNode ( URL url )
{ Iterator<DownloadsNode> i = nodes.iterator();
while ( i.hasNext() )
{ DownloadsNode node = i.next();
if (node.getUrl().equals(url))
return node;
}
return null;
}
public synchronized DownloadsNode addNode ( URL url )
{ DownloadsNode node = new DownloadsNode ( url );
nodes.add ( node );
return node;
}
public synchronized void deleteNode ( DownloadsNode node )
{ nodes.remove ( node );
}
public synchronized void accessAsAReader()
{
while(writersCount>0)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
readLock.lock();
readersCount++;
}
public synchronized void accessAsAWriter()
{
while(readersCount>0||writersCount>0)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
writeLock.lock();
writersCount++;
}
public synchronized void outAsAReader()
{
readLock.unlock();
readersCount--;
this.notifyAll();
}
public synchronized void outAsAWriter()
{
writeLock.unlock();
writersCount--;
this.notifyAll();
}
public Lock getreadLock()
{
return this.readLock;
}
}
DownloadsNode 类如下:
public class DownloadsNode {
private int waiting;
private URL url;
private cacheNode node;
private Lock readLock=new ReentrantReadWriteLock().readLock();
private Lock writeLock=new ReentrantReadWriteLock().writeLock();
private int readersCount=0,writersCount=0;
public DownloadsNode ( URL url )
{ waiting = 1;
this.url = url;
}
public URL getUrl()
{ return url;
}
public synchronized void setnodeC ( cacheNode node )
{ this.node = node;
}
public synchronized cacheNode getnodeC()
{ return node;
}
public synchronized int getwaiting()
{ return waiting;
}
public synchronized void addWaiting()
{ waiting++;
}
public synchronized void quitWaiting()
{ waiting--;
}
public synchronized void accessAsAReader()
{
while(writersCount>0)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
readLock.lock();
readersCount++;
}
public synchronized void accessAsAWriter()
{
while(readersCount>0||writersCount>0)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
writeLock.lock();
writersCount++;
}
public synchronized void outAsAReader()
{
readLock.unlock();
readersCount--;
this.notifyAll();
}
public synchronized void outAsAWriter()
{
writeLock.unlock();
writersCount--;
this.notifyAll();
}
public Lock getreadLock()
{
return this.readLock;
}
}
缓存类如下:
public class Cache {
private HashMap<URL,cacheNode> map;
private Lock readLock=new ReentrantReadWriteLock().readLock();
private Lock writeLock=new ReentrantReadWriteLock().writeLock();
private boolean added=false;
public Cache( int up_edge, int lim_inf, int debug )
{
//The content of this doesn't matter
}
public synchronized cacheNode findNode ( URL url )
{
cacheNode cacheNode= map.get ( url );
return cacheNode;
}
public synchronized cacheNode addNode ( resourceWeb resource, AtomicInteger referencias )
{
cacheNode node = new cacheNode ( resource, referencias );
map.put ( resource.getUrl(), node );
added=true;
return node;
}
public boolean getadded()
{
return added;
}
public synchronized void accessAsAReader()
{
while(writersCount>0)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
readLock.lock();
readersCount++;
}
public synchronized void accessAsAWriter()
{
while(readersCount>0||writersCount>0)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
writeLock.lock();
writersCount++;
}
public synchronized void outAsAReader()
{
readLock.unlock();
readersCount--;
this.notifyAll();
}
public synchronized void outAsAWriter()
{
writeLock.unlock();
writersCount--;
this.notifyAll();
}
public Lock getreadLock()
{
return this.readLock;
}
}
以前的所有类都从以下类中使用:
public class MainThread extends Thread{
private ArrayBlockingQueue<Petition> petitionQueue;
private Cache cache;
private int debug;
//constructor goes here but its content doesn't matter
public void run()
{
webResource webResource = null;
while(true)
{
try {
CacheNode cNode;
do
{
Petition petition = PetitionQueue.take();
//Searchs the web resource inside the cache
cache.accessAsAReader();
synchronized(this)
{
cNode = cache.findNode ( petition.getURL() );
}
if ( cNode != null ) // If it's found
{
cache.outAsAReader();
webResource = cNode.webResource;
}
else // if it's not found
{
cache.outAsAReader();
Downloads downloads=new Downloads(debug);
DownloadsNode node;
downloads.accessAsAReader();
synchronized(this)
{
node=downloads.findNode(petition.getURL());
}
**if(node!=null)
{
downloads.outAsAReader();
/*Another thread is downloading to store in the cache*/
/*We indicate that we are waiting. Here is my problem if I'm not wrong*/
node.accessAsAWriter();
synchronized(this)
{
node.incrementWaiting();
}
Condition waitingCondition=node.getReadLock().newCondition();
while(cache!=null&&!cache.getAdded())
{
waitingCondition.await();
}
/*Delete from count of waiting threads*/
synchronized(this)
{
nodo.decrementWaiting();
}
node.outAsAWriter();
/*If there aren't wating threads, delete the entry from downloads list*/
if(node.getWaiting()==0)
{
downloads.accessAsAWriter();
synchronized(this)
{
downloads.delete(node);
}
downloads.outAsAWriter();
}
}
else
{
downloads.outAsAReader();
downloads.accessAsAWriter();
synchronized(this)
{
node=downloads.addNode(petition.getURL());
}
downloads.outAsAWriter();
// Download the web resource.
webResource = petition.download();
cache.accessAsAWriter();
synchronized(this)
{
cNode = cache.addNode ( webResource, new AtomicInteger(1) );
}
cache.outAsAWriter();
/*Check if other threads are waiting*/
if(node.getWaiting()>0)
{
Condition condition2=nodo.getWriteLock().newCondition();
condition2.signalAll();
}
else
{
downloads.accessAsAWriter();
synchronized(this)
{
downloads.delete(node);
}
downloads.outAsAWriter();
}
}
}
//Sends response to the client
} while (true);
} catch (InterruptedException e) {
// TODO: poner una forma de terminar.
} catch (Exception e) {
}
}
}
}
有几点需要考虑:
-我必须在每个节点中创建条件变量,以便线程将因此等待并实现打开/关闭锁并保证互斥的方法。
- 如果一个线程正在下载其他线程感兴趣的资源,我使用条件变量等待,并在资源下载并存储在缓存中时说“停止等待”。我在那部分做错了什么?(所有这些都在 MainThread 类中)
-当保证互斥时,我是否必须将同步放在正确的方法中,执行以下方式: -Lock -synchronized(this) 并做我必须做的任何事情 -Unlock 还是我在两种方式都做同样的事情?在管理下载列表和缓存时,我必须建立批评区域,所以我认为有些部分在不需要的方法名称中添加同步,或者我错误地使用了读写锁。
注意:由于我翻译了变量和方法的名称以帮助理解,我可能写了一些不同的东西,但在我的程序中是正确的
非常感谢先进