我以为我对锁和基本的多线程概念有相当不错的理解,但我在这里搞砸了一些东西。
程序应该做的就是从用户那里接收文本文件的文件名和要使用的线程数,然后在将该数字返回给用户之前计算该文件中“http”链接的数量。
然而,就我的一生而言,我无法正确计算线程数。我尝试将“count”变量设为原子整数并使用“incrementAndGet()”函数,尝试将锁放在我认为应该在的代码中,并尝试指定必要的函数是同步的,一切都无济于事。
我一直在阅读有关锁、并发和诸如此类的内容,但显然我做错了什么。有人可以向我解释我需要在哪里/为什么在我的代码中放置锁(或者如何正确使用原子整数,如果这样更有效的话)?
我最初在使用“count”变量时有一个锁定(在任何循环之外,所以它实际上做了一些事情),但是当我运行程序时我收到了各种数字。
我的代码如下所示:
import java.io.*;
import java.util.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Count
{
static String fname;
static int count = 0;
public static void main(String[] arg)
{
Scanner in = new Scanner(System.in);
int numthreads;
if( arg.length > 0 )
{
fname = arg[0];
numthreads = Integer.parseInt(arg[1]);
}
else
{
System.out.println("File?");
fname = in.nextLine();
System.out.println("Num threads?");
numthreads = in.nextInt();
}
RandomAccessFile raf;
try
{
raf = new RandomAccessFile(fname,"r");
Thread[] T = new Thread[numthreads];
for(int i=0;i<numthreads;++i)
{
T[i] = new Thread(new Task(i,numthreads,raf));
T[i].start();
}
for(Thread t : T)
{
try
{
t.join();
}
catch (InterruptedException e)
{
System.out.println("Thread join failed!");
e.printStackTrace();
System.exit(0);
}
}
System.out.println("The total is: "+count);
}
catch(IOException e)
{
System.out.println("Could not read file");
}
}
}
class Task implements Runnable
{
int myid;
int totaltasks;
RandomAccessFile raf;
ReentrantLock L = new ReentrantLock();
public Task(int myid, int totaltasks, RandomAccessFile raf)
{
this.myid=myid;
this.totaltasks=totaltasks;
this.raf = raf;
}
@Override
public void run()
{
try
{
long filesize = raf.length(); //length of the entire file
long sz = filesize / totaltasks; //length of entire file divided by number of threads gives thread size
long start = myid*sz; // thread's number * size of thread. How we find start of thread in the file
raf.seek(start);
if(start != 0 )
{
raf.readLine();
}
while(raf.getFilePointer() < (start+sz))
{
String s = raf.readLine();
Scanner sc = new Scanner(s);
while(sc.hasNext())
{
String w = sc.next();
if( w.startsWith("http://"))
{
Count.count++;
}
}
}
}
catch(IOException e)
{
System.out.println("IO error!");
}
}
}
如果这里的工作比我需要在适当的地方使用锁更大的问题,请告诉我,我至少会有一些工作要做,但据我所知,这应该只是表演的问题正确锁定,我要么不了解它们如何正常工作,要么只是将它们放在所有错误的地方。