import java.io.*;
import java.util.*;
import java.util.zip.*;public class GZipThread extends Thread {
private List pool;
private static int filesCompressed = 0;

public GZipThread(List pool) {
this.pool = pool;
} private static synchronized void incrementFilesCompressed() {
// 所有线程同步同一个class对象,操作同一个静态filesCompressed
filesCompressed++;
} public void run() {
while (filesCompressed != GZipAllFiles.getNumberOfFilesToBeCompressed()) {
File input = null;
synchronized (pool) {
while (pool.isEmpty()) {
if (filesCompressed == GZipAllFiles
.getNumberOfFilesToBeCompressed()) {
System.out.println("Thread ending");
return;
}
try {
pool.wait();//得到通知,获得所等待的锁就执行wait()后面的语句
} catch (InterruptedException ex) {
}
}//while (pool.isEmpty())循环结束
input = (File) pool.remove(pool.size() - 1);
incrementFilesCompressed();
}//synchronized (pool)同步结束
if (!input.getName().endsWith(".gz")) {// 不压缩已经压缩过的文件
try {
InputStream in = new FileInputStream(input);
in = new BufferedInputStream(in);
File output = new File(input.getParent(), input.getName()
+ ".gz");
if (!output.exists()) {// 不覆盖已经存在的文件
OutputStream out = new FileOutputStream(output);
out = new GZIPOutputStream(out);
out = new BufferedOutputStream(out);
int b;
while ((b = in.read()) != -1)
out.write(b);
out.flush();
out.close();
in.close();
}
} catch (IOException ex) {
System.err.println(ex);
}
}
}//最外层while结束
}//run()结束
}
import java.io.*;
import java.util.*;public class GZipAllFiles { public final static int THREAD_COUNT = 4;
public static int filesToBeCompressed = -1; public static void main(String[] args) {
Vector pool=new Vector();
GZipThread[] threads=new GZipThread[THREAD_COUNT];
for(int i=0;i<threads.length;i++){
threads[i]=new GZipThread(pool);
threads[i].start();
}
int totalFiles=0;
for(int i=0;i<args.length;i++){
File f=new File(args[i]);
if(f.exists()){
if(f.isDirectory()){//文件是一个目录时****
File[] files=f.listFiles();
for(int j=0;j<files.length;i++){
if(!files[j].isDirectory()){//不递归处理目录
totalFiles++;
synchronized(pool){
pool.add(0, files[j]);
pool.notifyAll();
}
}
  }//内层for结束
}//****处for结束
else{
totalFiles++;
synchronized(pool){
pool.add(0,f);
pool.notifyAll();
}
}//else结束
}
}//最外层for结束
filesToBeCompressed=totalFiles;
for(int i=0;i<threads.length;i++){//没有文件再添加到池中,中断等待的线程
threads[i].interrupt();
}
} public static int getNumberOfFilesToBeCompressed() {
return filesToBeCompressed;
}}
书上说incrementFilesCompressed()方法必须是同步静态方法,不能是同步实例方法,filesCompressed是静态的了,为何incrementFilesCompressed必须是静态的,就算是实例方法,每个对象都有这个方法,但操作的类变量是共享的呀,求解释?

解决方案 »

  1.   

    你是说这个方法为何是静态的?
    如果不是同步的问题,那么是不是静态均可。因为它不需要访问non-static变量这个方法被定义为同步的,目的就是两个线程不会同时操作那个filesCompressed++。现在static synchronized,任何GZipThread实例都会被同步。如果变成non-static synchronized,那么这个同步,只对当前对象有效。不同实例间不会互锁。起不到同步的作用。
      

  2.   

    import java.awt.*;
        import java.awt.event.*;
    public class Jpro13_5 extends Frame{
    protected static final String[] NAMES = {"A","B"};
    private int accounts[] = {1000,1000};
    private TextArea info = new TextArea(5,40);
    private TextArea status = new TextArea(5,40);
    public Jpro13_5 (){
    super("Jpro13_5");
    setLayout(new GridLayout(2,1));
    add(makePanel(info,"Accounts"));
    add(makePanel(status,"Threads"));
    validate();pack();setVisible(true);
    Jpro13_5Thread A = new  Jpro13_5Thread(0,this,status);
    Jpro13_5Thread B = new  Jpro13_5Thread(1,this,status);
    addWindowListener(new WindowAdapter(){
    public void windowClosing(WindowEvent we){
    System.exit(0);
    }
    });
    }
    public synchronized void transfer(int from,int into,int amount){
    info.append("\nAccount A: $" + accounts[0]);
    info.append("\tAccount B: $" + accounts[1]);
    info.append("\n=> $" + amount + " from " + NAMES[from] + " to " + NAMES[into]);
    while(accounts[from] < amount){
    try{
    wait();
    }catch(InterruptedException ie){
    System.err.println("Error: " + ie);
    }
    }
    accounts[from] -= amount;
    accounts[into] +=amount;
    notify();
    }
    private Panel makePanel(TextArea text,String title){
    Panel p = new Panel();
    p.setLayout(new BorderLayout());
    p.add("North",new Label(title));p.add("Center",text);
    return p;
    }
    public static void main(String args[]){
    Jpro13_5 bank = new Jpro13_5();
    }
    }
    class Jpro13_5Thread extends Thread{
    private Jpro13_5 bank;
    private int id;
    private TextArea display;
    public Jpro13_5Thread(int _id,Jpro13_5 _bank,TextArea _display){
    bank = _bank;
    id = _id;
    display = _display;
    start();
    }
    public void run(){
    while(true){
    int amount = (int)(900*Math.random());
    display.append("\nThread " + Jpro13_5.NAMES[id] + " sends $ " + amount + " into " + Jpro13_5.NAMES[(1-id)]);
    try{
    sleep(50);
    }catch(InterruptedException ie){
    System.err.println("Interrupted");
    }
    bank.transfer(id,1-id,amount);
    }
    }
    }
    那public synchronized void transfer(int from,int into,int amount)这个方法不是静态的,不也同步了吗?结合这个代码您再解释下,谢谢
      

  3.   

    因为Frame这个,只有一个实例在处理
      

  4.   

    这不只一个实例吧,最上面的代码,那个方法我去掉static,代码也没有运行错误
      

  5.   

    看错了,是只有一个实例运行,但我问的最上面的代码,有四个实例,我认为你说的对,没有static,无法实现对所有线程同步同一个class对象,可是我想不通的是:那个方法去掉static,测试了一下,没有问题,想不通另外for(int j=0;j<files.length;i++){
                            if(!files[j].isDirectory()){//不递归处理目录
                                totalFiles++;
                                synchronized(pool){
                                    pool.add(0, files[j]);
                                    pool.notifyAll();
                            }
     里面的i是j,写错了
      

  6.   

    这几天看了不同的资料,你说的还是对的,static去掉后,无法锁定共享资源,不能锁定GZipThread类的所有实类。至于去掉static后,测试结果没有错误,应该是测试文件太少的原因