??xml version="1.0" encoding="utf-8" standalone="yes"?>久久亚洲一区,blacked蜜桃精品一区,国产自产自拍视频在线观看http://www.aygfsteel.com/jiangshachina/category/53896.html同是Java爱好者,盔R何必曾相识Q?lt;br>    a cup of Java, cheers!zh-cnTue, 22 Apr 2014 12:46:37 GMTTue, 22 Apr 2014 12:46:37 GMT60Javaq发基础实践--死锁(?http://www.aygfsteel.com/jiangshachina/archive/2013/12/29/408180.htmlSha JiangSha JiangSun, 29 Dec 2013 12:19:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2013/12/29/408180.htmlhttp://www.aygfsteel.com/jiangshachina/comments/408180.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2013/12/29/408180.html#Feedback1http://www.aygfsteel.com/jiangshachina/comments/commentRss/408180.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/408180.html
Javaq发基础实践--死锁
本文?a href="http://www.aygfsteel.com/jiangshachina/category/53896.html">Javaq发基础实践pd中的一,介绍了最单的死锁场景Qƈ使用jstack产生的thread dump来查找死锁?2013.12.29最后更?

1. 死锁
Z能够l护U程的安全性,Java提供的锁机制Q但不恰当地使用锁则可能产生死锁。死锁是q发~程中一个无法绕开的问题。只要在一个Q务中使用了一个以上的锁,那么存在死锁的风险?br />死锁产生的直接原因非常简单,即两个线E在怺{待Ҏ所执有的锁?br />
2. 锁顺序死?/span>
在死锁场景中Q最典型的就是锁序死锁Q代码清?是一个很常见的示例?br />
清单1
public class DeadLock {

    
private Object leftLock = new Object();
    
private Object rightLock = new Object();

    
public void leftRight() {
        
synchronized (leftLock) {
            
try {
                TimeUnit.SECONDS.sleep(
3);
            } 
catch (InterruptedException e) {
                e.printStackTrace();
            }

            
synchronized (rightLock) {
                System.out.println(
"leftRight");
            }
        }
    }

    
public void rightLeft() {
        
synchronized (rightLock) {
            
try {
                TimeUnit.SECONDS.sleep(
3);
            } 
catch (InterruptedException e) {
                e.printStackTrace();
            }

            
synchronized (leftLock) {
                System.out.println(
"leftRight");
            }
        }
    }

    
public static void main(String[] args) {
        
final DeadLock deadLock = new DeadLock();

        Thread t1 
= new Thread(new Runnable() {

            @Override
            
public void run() {
                deadLock.leftRight();
            }
        });

        Thread t2 
= new Thread(new Runnable() {

            @Override
            
public void run() {
                deadLock.rightLeft();
            }
        });

        t1.start();
        t2.start();
    }
}

3. Thread Dump
JDK提供了一l命令行工具Q其中就包括jstack。通过jstack可以获取当前正运行的Javaq程的java stack和native stack信息。如果Javaq程崩溃了,也可以通过它来获取core file中的java stack和native stack信息Q以方便我们定位问题?br />Z能够使用jstack去输出目标Javaq程的thread dumpQ首先必要弄清楚在执行清单1的程序时Q该E序的进E号。JDK提供的另一个命令行工具jps可以获取pȝ中所有Javaq程的相关信息?br />在命令行H口中执行命?em>jpsQ即可以得到清单2所C的l果
清单2
C:\Documents and Settings\Administrator>jps
2848
4552 DeadLock
5256 Jps
其中4552是在笔者机器上执行E序DeadLock时所生成Javaq程的进E号?br />然后再执行命?em>jstack 4552Q在W者的机器上就会得到清?所C的l果
清单3
C:\Documents and Settings\Administrator>jstack 
4552
2013-12-29 18:45:41
Full thread dump Java HotSpot(TM) Client VM (
23.25-b01 mixed mode, sharing):

"DestroyJavaVM" prio=6 tid=0x00878800 nid=0xd00 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" prio=6 tid=0x02b56c00 nid=0x14ec waiting for monitor entry [0x02fdf000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at concurrency.deadlock.DeadLock.rightLeft(DeadLock.java:
33)
        - waiting to lock <0x22be6598> (a java.lang.Object)
        - locked <0x22be65a0> (a java.lang.Object)
        at concurrency.deadlock.DeadLock$
2.run(DeadLock.java:53)
        at java.lang.Thread.run(Thread.java:
724)

"Thread-0" prio=6 tid=0x02b55c00 nid=0x354 waiting for monitor entry [0x02f8f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at concurrency.deadlock.DeadLock.leftRight(DeadLock.java:
19)
        - waiting to lock <0x22be65a0> (a java.lang.Object)
        - locked <0x22be6598> (a java.lang.Object)
        at concurrency.deadlock.DeadLock$
1.run(DeadLock.java:45)
        at java.lang.Thread.run(Thread.java:
724)

"Service Thread" daemon prio=6 tid=0x02b34800 nid=0x133c runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread0" daemon prio=10 tid=0x02b13800 nid=0x10fc waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Attach Listener" daemon prio=10 tid=0x02b11c00 nid=0x1424 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x02b10800 nid=0x1100 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=8 tid=0x02af4c00 nid=0x1238 in Object.wait() [0x02daf000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x22b60fb8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:
135)
        - locked <0x22b60fb8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:
151)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:
189)

"Reference Handler" daemon prio=10 tid=0x02af0000 nid=0x12e8 in Object.wait() [0x02d5f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x22b60da0> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:
503)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:
133)
        - locked <0x22b60da0> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=10 tid=0x02aee400 nid=0x129c runnable

"VM Periodic Task Thread" prio=10 tid=0x02b48000 nid=0x89c waiting on condition

JNI global references: 
117


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x02af4a3c (object 0x22be6598
, a java.lang.Object),
  which is held by 
"Thread-0"
"Thread-0":
  waiting to lock monitor 0x02af310c (object 0x22be65a0
, a java.lang.Object),
  which is held by 
"Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at concurrency.deadlock.DeadLock.rightLeft(DeadLock.java:
33)
        - waiting to lock <0x22be6598> (a java.lang.Object)
        - locked <0x22be65a0> (a java.lang.Object)
        at concurrency.deadlock.DeadLock$
2.run(DeadLock.java:53)
        at java.lang.Thread.run(Thread.java:
724)
"Thread-0":
        at concurrency.deadlock.DeadLock.leftRight(DeadLock.java:
19)
        - waiting to lock <0x22be65a0> (a java.lang.Object)
        - locked <0x22be6598> (a java.lang.Object)
        at concurrency.deadlock.DeadLock$
1.run(DeadLock.java:45)
        at java.lang.Thread.run(Thread.java:
724)

Found 
1 deadlock.
在上q输ZQ我们可以很明确地看C个死?br />
"Thread-1":
  waiting to lock monitor 0x02af4a3c (object 0x22be6598
, a java.lang.Object),
  which is held by 
"Thread-0"
"Thread-0":
  waiting to lock monitor 0x02af310c (object 0x22be65a0
, a java.lang.Object),
  which is held by 
"Thread-1"
q且它还标明了程序是在哪个地Ҏ发现了上q死?br />
"Thread-1":
        at concurrency.deadlock.DeadLock.rightLeft(DeadLock.java:
33)
        - waiting to lock <0x22be6598> (a java.lang.Object)
        - locked <0x22be65a0> (a java.lang.Object)
        at concurrency.deadlock.DeadLock$
2.run(DeadLock.java:53)
        at java.lang.Thread.run(Thread.java:
724)
"Thread-0":
        at concurrency.deadlock.DeadLock.leftRight(DeadLock.java:
19)
        - waiting to lock <0x22be65a0> (a java.lang.Object)
        - locked <0x22be6598> (a java.lang.Object)
        at concurrency.deadlock.DeadLock$
1.run(DeadLock.java:45)
        at java.lang.Thread.run(Thread.java:
724)

4. 结
死锁产生的直接原因非常简单,即两个线E在怺{待Ҏ所执有的锁。锁序死锁是其中最l典的场景,此外q有动态的锁顺序死锁。虽然表现Ş式有所不同Q但本质上都是两个线E在以不同的序来获取相同锁Ӟ发生了死锁问题?br />使用thread dump可以帮助我们分析死锁产生的原因。除了直接用jstack命o来获取thread dump输出以外QJDKq提供了jvisualvm工具Q它能以可视化的方式展示JavaE序的进E号q导出thread dump?/div>

Sha Jiang 2013-12-29 20:19 发表评论
]]>
Javaq发基础实践--分而治??http://www.aygfsteel.com/jiangshachina/archive/2013/10/23/405577.htmlSha JiangSha JiangWed, 23 Oct 2013 15:27:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2013/10/23/405577.htmlhttp://www.aygfsteel.com/jiangshachina/comments/405577.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2013/10/23/405577.html#Feedback0http://www.aygfsteel.com/jiangshachina/comments/commentRss/405577.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/405577.html阅读全文

Sha Jiang 2013-10-23 23:27 发表评论
]]>
Javaq发基础实践--退ZQ务II(?http://www.aygfsteel.com/jiangshachina/archive/2013/10/07/404690.htmlSha JiangSha JiangMon, 07 Oct 2013 08:55:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2013/10/07/404690.htmlhttp://www.aygfsteel.com/jiangshachina/comments/404690.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2013/10/07/404690.html#Feedback3http://www.aygfsteel.com/jiangshachina/comments/commentRss/404690.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/404690.html
Javaq发基础实践--退ZQ务II
?a href="http://www.aygfsteel.com/jiangshachina/category/53896.html">本系?/a>?a href="http://www.aygfsteel.com/jiangshachina/archive/2013/09/21/404269.html">上一?/a>中所q的退出ƈ发Q务的方式都是ZJDK 5之前的APIQ本文将介绍使用由JDK 5引入的ƈ发工具包中的API来退ZQ务?2013.10.08最后更?

    在本pd的前一中讲述了三U退出ƈ发Q务的方式--停止U程Q可取消的Q务;中断Q但都是ZJDK 5之前的API。本将介绍由JDK 5引入的java.concurrent包中的Future来取消Q务的执行?br />
1. Future模式
    Future是ƈ发编E中的一U常见设计模式,它相当于是Proxy模式与Thread-Per-Message模式的结合。即Q每ơ都创徏一个单独的U程L行一个耗时的Q务,q且创徏一个Future对象L有实际的d对象Q在来需要的时候再去获取实际Q务的执行l果?br />依然先创Z个用于扫描文件的dFileScannerTaskQ如代码清单1所C,
清单1
public class FileScannerTask implements Runnable {

    
private File root = null;

    
private ArrayList<String> filePaths = new ArrayList<String>();

    
public FileScannerTask(File root) {
        
if (root == null || !root.exists() || !root.isDirectory()) {
            
throw new IllegalArgumentException("root must be directory");
        }

        
this.root = root;
    }

    @Override
    
public void run() {
        travleFiles(root);
    }

    
private void travleFiles(File parent) {
        String filePath 
= parent.getAbsolutePath();
        filePaths.add(filePath);

        
if (parent.isDirectory()) {
            File[] children 
= parent.listFiles();
            
if (children != null) {
                
for (File child : children) {
                    travleFiles(child);
                }
            }
        }
    }

    
public List<String> getFilePaths() {
        
return (List<String>) filePaths.clone();
    }
}
此处的文件扫描Q务,提供了一个getFilePaths()Ҏ以允讔R旉可以取出当前已扫描过的文件的路径(相当于一个Q务快?。然后,创徏一个针对该d的Futurec,如代码清?所C,
清单2
public class FileScannerFuture {

    
private FileScannerTask task = null;

    
public FileScannerFuture(FileScannerTask task) {
        
new Thread(task).start();
        
this.task = task;
    }

    
public List<String> getResult() {
        
return task.getFilePaths();
    }
}
FileScannerFuture持有FileScannerTask的引用,q创Z个独立的U程来执行该d。在d的执行过E中Q应用程序可以在"未来"的某个时d获取一个Q务的快照Q如代码清单3所C,
清单3
public static void main(String[] args) throws Exception {
    FileScannerFuture future 
= new FileScannerFuture(new FileScannerTask(new File("C:")));

    TimeUnit.SECONDS.sleep(
1);
    List
<String> filePaths1 = future.getResult();
    System.out.println(filePaths1.size());

    TimeUnit.SECONDS.sleep(
1);
    List
<String> filePaths2 = future.getResult();
    System.out.println(filePaths2.size());
}

2. 使用q发工具包中的Future实现
    前面所展示的Future实现十分的简陋,没有实际应用的意义。用FileScannerFutureQ应用程序在获取filePathsӞ无法得知其获取的是否为最l结果,x法判断FileScannerTask是否已经完成。而且Q也不能在必要时停止FileScannerTask的执行。毫无疑问,由JDK 5引入的ƈ发工具包肯定会提供此cd用工P如FutureTask。ؓ了用ƈ发工具包中的FutureQ需要修改前q的FileScannerTask实现Q让其实现Callable接口Q如代码清单4所C,
清单4
public class FileScannerTask implements Callable<List<String>> {

    
private File root = null;

    
private List<String> filePaths = new ArrayList<String>();

    
public FileScannerTask(File root) {
        
if (root == null || !root.exists() || !root.isDirectory()) {
            
throw new IllegalArgumentException("root must be directory");
        }

        
this.root = root;
    }

    @Override
    
public List<String> call() {
        travleFiles(root);
        
return filePaths;
    }

    
private void travleFiles(File parent) {
        String filePath 
= parent.getAbsolutePath();
        filePaths.add(filePath);

        
if (parent.isDirectory()) {
            File[] children 
= parent.listFiles();
            
if (children != null) {
                
for (File child : children) {
                    travleFiles(child);
                }
            }
        }
    }

    
public List<String> getFilePaths() {
        
return (List<String>) filePaths.clone();
    }
}
应用E序也要相应的修Ҏ如代码清?所C,使用ExecutorService来提交Q务,q创Z个Future/FutureTask实例?br />
清单5
public static void main(String[] args) {
    ExecutorService executorService 
= Executors.newCachedThreadPool();
    Future
<List<String>> future = executorService.submit(new FileScannerTask(new File("C:")));

    
try {
        List
<String> filePaths = future.get();
        System.out.println(filePaths.size());
    } 
catch (InterruptedException e) {
        e.printStackTrace();
    } 
catch (ExecutionException e) {
        e.printStackTrace();
    }

    executorService.shutdown();
}
此处是调用Future.get()Ҏ来获取Q务的执行l果Q如果Q务没有执行完毕,那么该方法将会被d。该Future实现的好处就是,正常情况下,只有在Q务执行完毕之后才能获取其l果Q以保证该结果是最l执行结果?br />
3. 使用Future取消d
    Future除了定义有可获取执行l果的getҎ(get()以及get(long timeout, TimeUnit unit))Q还定义了三个方法:cancel()QisCancelled()以及isDone()Q用于取消Q务,以及判定d是否已被取消、已执行完毕。如代码清单6所C,
清单6
public interface Future<V> {

    
boolean cancel(boolean mayInterruptIfRunning);
    
boolean isCancelled();
    
boolean isDone();
    
}
其中Qcancel()Ҏ中的boolean参数若ؓtrueQ表C在取消该Q务时Q若执行该Q务的U程仍在q行中,则对其进行中断。如代码清单7所C,若Q务执行超时了Q那么就取消它?br />
清单7
public static void main(String[] args) {
    ExecutorService executorService 
= Executors.newCachedThreadPool();
    Future
<List<String>> future = executorService.submit(new FileScannerTask(new File("C:")));

    
try {
        List
<String> filePaths = future.get(1, TimeUnit.SECONDS);
        System.out.println(filePaths.size());
    } 
catch (InterruptedException e) {
        e.printStackTrace();
    } 
catch (ExecutionException e) {
        e.printStackTrace();
    } 
catch (TimeoutException e) {
        e.printStackTrace();
    } 
finally {
        future.cancel(
true);
    }

    executorService.shutdown();
}
在实际应用中Q取消Q务的原由肯定不仅仅只是超时这么简单,q可能是׃接受C用户的指令。此Ӟ则可能会从另一个独立线E去取消该Q务。除了取消Q务之外,有时q需要取ZQ务中已经生成的部分结果。但Z能够响应d的退出,首先需要修改FileScannerTaskQ得当d被取?中断)Ӟd能够真正的快速停止ƈq回Q如代码清单8所C,
清单8
public class FileScannerTask implements Callable<List<String>> {

    

    
private void travleFiles(File parent) {
        
if (Thread.currentThread().isInterrupted()) {
            
return;
        }

        String filePath 
= parent.getAbsolutePath();
        filePaths.add(filePath);

        
if (parent.isDirectory()) {
            File[] children 
= parent.listFiles();
            
if (children != null) {
                
for (File child : children) {
                    travleFiles(child);
                }
            }
        }
    }

    
}
相应C改应用程序的代码Q如代码清单9所C,
清单9
public static void main(String[] args) {
    ExecutorService executorService 
= Executors.newCachedThreadPool();
    FileScannerTask task 
= new FileScannerTask(new File("C:"));
    
final Future<List<String>> future = executorService.submit(task);
    
    
new Thread(new Runnable() {
        
        @Override
        
public void run() {
            
try {
                TimeUnit.SECONDS.sleep(
1);
            } 
catch (InterruptedException e) {
                e.printStackTrace();
            }
            future.cancel(
true);
        }
    }).start();
    
    
try {
        List
<String> filePaths = future.get();
        System.out.println(filePaths.size());
    } 
catch (InterruptedException e) {
        e.printStackTrace();
    } 
catch (ExecutionException e) {
        e.printStackTrace();
    } 
catch (CancellationException e) {
        List
<String> filePaths = task.getFilePaths();
        System.out.println(
"Partly result: " + filePaths.size());
    }
    
    executorService.shutdown();
}
׃可知Q此处用Future.cancel(true)的本质依然是利用了线E的中断机制?br />
4. 结
    使用Future可以在Q务启动之后的特定时机再去获取d的执行结果。由JDK 5引入的ƈ发工具包中提供的Future实现不仅可以获取d的执行结果,q可以用于取消Q务的执行?/div>

Sha Jiang 2013-10-07 16:55 发表评论
]]>
Javaq发基础实践--退ZQ务I(?http://www.aygfsteel.com/jiangshachina/archive/2013/09/21/404269.htmlSha JiangSha JiangSat, 21 Sep 2013 11:11:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2013/09/21/404269.htmlhttp://www.aygfsteel.com/jiangshachina/comments/404269.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2013/09/21/404269.html#Feedback0http://www.aygfsteel.com/jiangshachina/comments/commentRss/404269.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/404269.html
Javaq发基础实践--退ZQ务I
计划写一?Javaq发基础实践"pdQ算作本人对Javaq发学习与实늚单ȝ。本文是该系列的W一,介绍了退出ƈ发Q务的最单方法?2013.09.25最后更?

在一个ƈ发Q务被启动之后Q不要期望它L会执行完成。由于时间限Ӟ资源限制Q用h作,甚至是Q务中的异?其是运行时异常)Q?..都可能造成d不能执行完成。如何恰当地退ZQ务是一个很常见的问题,而且实现Ҏ也不一而?/span>

1. d
创徏一个ƈ发Q务,递归地获取指定目录下的所有子目录与文件的l对路径Q最后再这些\径信息保存到一个文件中Q如代码清单1所C:
清单1
public class FileScanner implements Runnable {

    
private File root = null;

    
private List<String> filePaths = new ArrayList<String>();

    
public FileScanner1(File root) {
        
if (root == null || !root.exists() || !root.isDirectory()) {
            
throw new IllegalArgumentException("root must be legal directory");
        }

        
this.root = root;
    }

    @Override
    
public void run() {
        travleFiles(root);
        
try {
            saveFilePaths();
        } 
catch (Exception e) {
            e.printStackTrace();
        }
    }

    
private void travleFiles(File parent) {
        String filePath 
= parent.getAbsolutePath();
        filePaths.add(filePath);

        
if (parent.isDirectory()) {
            File[] children 
= parent.listFiles();
            
for (File child : children) {
                travleFiles(child);
            }
        }
    }

    
private void saveFilePaths() throws IOException {
        FileWriter fos 
= new FileWriter(new File(root.getAbsoluteFile()
                
+ File.separator + "filePaths.out"));
        
for (String filePath : filePaths) {
            fos.write(filePath 
+ "\n");
        }
        fos.close();
    }
}

2. 停止U程
有一个很直接Q也很干脆的方式来停止线E,是调用Thread.stop()ҎQ如代码清单2所C:
清单2
public static void main(String[] args) throws Exception {
    FileScanner task 
= new FileScanner(new File("C:"));
    Thread taskThread 
= new Thread(task);
    taskThread.start();

    TimeUnit.SECONDS.sleep(
1);
    taskThread.stop();
}
但是Q地球h都知道Thread.stop()在很久很久之前就不推荐用了。根?a >官方文档的介l,该方法存在着固有的不安全性。当停止U程Ӟ会释放该线E所占有的全部监视锁Q这׃造成受这些锁保护的对象的不一致性。在执行清单2的应用程序时Q它的运行结果是不确定的。它可能会输Z个文Ӟ其中包含部分的被扫描q的目录和文件。但它也很有可能什么也不输出,因ؓ在执行FileWriter.write()的过E中Q可能由于线E停止而造成了I/O异常Q得最l无法得到输出文件?/span>

3. 可取消的d
另外一U十分常见的途径是,在设计之初,我们׃d是可被取消的。一般地Q就是提供一个取消标志或讑֮一个取消条Ӟ一旦Q务遇到该标志或满了取消条gQ就会结束Q务的执行。如代码清单3所C:
清单3
public class FileScanner implements Runnable {

    
private File root = null;

    
private List<String> filePaths = new ArrayList<String>();

    
private boolean cancel = false;

    
public FileScanner(File root) {
        
    }

    @Override
    
public void run() {
        
    }

    
private void travleFiles(File parent) {
        
if (cancel) {
            
return;
        }

        String filePath 
= parent.getAbsolutePath();
        filePaths.add(filePath);

        
if (parent.isDirectory()) {
            File[] children 
= parent.listFiles();
            
for (File child : children) {
                travleFiles(child);
            }
        }
    }

    
private void saveFilePaths() throws IOException {
        
    }

    
public void cancel() {
        cancel 
= true;
    }
}
新的FileScanner实现提供一个cancel标志QtravleFiles()会遍历新的文件之前检该标志Q若该标志ؓtrueQ则会立卌回。代码清?是用新d的应用程序?/span>
清单4
public static void main(String[] args) throws Exception {
    FileScanner task 
= new FileScanner(new File("C:"));
    Thread taskThread 
= new Thread(task);
    taskThread.start();

    TimeUnit.SECONDS.sleep(
3);
    task.cancel();
}
但有些时候用可取消的Q务,q不能快速地退ZQ务。因ZQ务在取消标志之前,可能正处于等待状态,甚至可能被阻塞着。对清单2中的FileScannerE作修改Q让每次讉K新的文g之前先睡?0U钟Q如代码清单5所C:
清单5
public class FileScanner implements Runnable {

    

    
private void travleFiles(File parent) {
        
try {
            TimeUnit.SECONDS.sleep(
10);
        } 
catch (InterruptedException e) {
            e.printStackTrace();
        }

        
if (cancel) {
            
return;
        }

        
    }

    
private void saveFilePaths() throws IOException {
        
    }

    
public void cancel() {
        cancel 
= true;
    }
}
再执行清?中的应用E序Ӟ可能发现dq没有很快速的退出,而是又等待了大约7U钟才退出。如果在查cancel标志之前要先获取某个受锁保护的资源,那么该Q务就会被dQƈ且无法确定何时能够退出。对于这U情况,需要用中断了?/span>

4. 中断
中断是一U协作机Ӟ它ƈ不会真正地停止一个线E,而只是提醒线E需要被中断Qƈ线E的中断状态设|ؓtrue。如果线E正在执行一些可抛出InterruptedException的方法,如Thread.sleep()QThread.join()和Object.wait()Q那么当U程被中断时Q上q方法就会抛出InterruptedExceptionQƈ且中断状态会被重新设|ؓfalse。Q务程序只要恰当处理该异常Q就可以正常地退ZQ务。对清单5再稍作修改,卻I如果d在睡眠时遇上了InterruptedExceptionQ那么就取消d。如代码清单6所C:
清单6
public class FileScanner implements Runnable {

    

    
private void travleFiles(File parent) {
        
try {
            TimeUnit.SECONDS.sleep(
10);
        } 
catch (InterruptedException e) {
            cancel();
        }

        
if (cancel) {
            
return;
        }

        
    }

    
}
同时清?中的应用E序Q此时将调用Thread.interrupt()ҎM断线E,如代码清?所C:
清单7
public static void main(String[] args) throws Exception {
    FileScanner3 task 
= new FileScanner3(new File("C:"));
    Thread taskThread 
= new Thread(task);
    taskThread.start();

    TimeUnit.SECONDS.sleep(
3);
    taskThread.interrupt();
}
或者更q一步,仅用中断状态来控制E序的退出,而不再用可取消的Q?卻I删除cancel标志)Q将清单6中的FileScanner修改成如下:
清单8
public class FileScanner implements Runnable {

    

    
private void travleFiles(File parent) {
        
try {
            TimeUnit.SECONDS.sleep(
10);
        } 
catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        
if (Thread.currentThread().isInterrupted()) {
            
return;
        }

        
    }

    
}
再次执行清单7的应用程序后Q新的FileScanner也能x的退Z。值得注意的是Q因为当sleep()Ҏ抛出InterruptedExceptionӞ该线E的中断状态将又会被设|ؓfalseQ所以必要再次调用interrupt()Ҏ来保存中断状态,q样在后面才可以利用中断状态来判定是否需要返回travleFiles()Ҏ。当Ӟ对于此处的例子,在收到InterruptedException时也可以选择直接q回Q如代码清单9所C:
清单9
public class FileScanner implements Runnable {

    

    
private void travleFiles(File parent) {
        
try {
            TimeUnit.SECONDS.sleep(
10);
        } 
catch (InterruptedException e) {
            
return;
        }

        
    }

    
}

5 结
本文介绍了三U简单的退出ƈ发Q务的ҎQ停止线E;使用可取消Q务;使用中断。毫无疑问,停止U程是不可取的。用可取消的Q务时Q要避免d׃被阻塞而无法及Ӟ甚至永远无法被取消。一般地Q恰当地使用中断是取消Q务的首选方式?/span>


Sha Jiang 2013-09-21 19:11 发表评论
]]>
վ֩ģ壺 Ȫ| | | | | Ϫ| ˮ| | ͭϿ| | | Ϸ| | | ɳ| ʻ| | | | | Ϫ| | | | | | | | ɽ| | Ϫ| | | ɣֲ| | | Ӣ| | | ̫| |