此時程序中最多有幾個存活的線程,個人認為應該是4個,怎么就是看不到是4個的結果呢?
package Test;
public class Testthread{
public static void main(String[] args){
//測定當前活動的線程數目 肯定有一個主線程在運行
System.out.println("=========header========"+Thread.activeCount());
ThreadTest tt=new ThreadTest();
RunTest rt=new RunTest(); //在下面新建線程里被啟動
new Thread(rt).start(); //新建立的一個線程 啟動
tt.start(); //已經建立的線程 啟動
System.out.println("===========footer======"+Thread.activeCount());
}
}
class ThreadTest extends Thread{
public void run(){
System.out.println("==========I'm over thread=========");
}
}
class RunTest implements Runnable{
public void run(){
System.out.println("==========I'm over runnable==========");
}
}
打印結果:
第一類結果 (次序有時不同)
=========header========1
===========footer======3
==========I'm over thread=========
==========I'm over runnable==========
第二類結果
=========header========1
==========I'm over runnable==========
===========footer======2
==========I'm over thread=========
我們在開發JAVA WEB
一、MVC 二、 用MVC Servlet Servlet Servlet Servlet 代碼程序如下: PrintWriter output;//成員變量 @Override IOException { response.setContentType("text/html;charset=gb2312"); String name = request.getParameter("name"); output=response.getWriter(); Thread. } e.printStackTrace(); } output.write(name); } } 該實例中定義了一個實例變量output 第一次請求: 大家看到這頁面什么數據也沒有,就是說那姓名沒有打印出來,那跑到哪里去了呢?看第二個用戶請求的情況。 第二個用戶請求地址:http://127.0.0.1:8080/Test2/securityTest?name=b 可以看到,原來a 可以想像在暫停5000 從內存模型來看Servlet JAVA 根據內存模型,我們可以得到如下的線程調度表: 可以看出,由于b 解決方法: 從上面的分析中,我們知道導致線程不安全的主要原因在于實例變量的使用不當,下面就提出如下三種解決方法 第一, 代碼如下: 其實這方法也就相當于是同步方法的效果吧。 第二.同步對共享數據的操作。我們所熟悉的就是用synchronized PrintWriter output; @Override response.setContentType("text/html;charset=gb2312"); String name = request.getParameter("name"); Synchronized(this){ output=response.getWriter(); Thread. } e.printStackTrace(); } output.write(name); }} 第三:避免使用實例變量,而使用局部變量。因為Servlet線程不安全的原因是由實例變量引起,所以我們可以避免使用實例變量,而使用局部變量,線程之間很難直接訪問局部變量 ,這樣就從根本上解決了這一問題。 在本例子中,就是將output放在service方法中當局部變量 。 @Override HttpServletResponse response) PrintWriter output; response.setContentType("text/html;charset=gb2312"); String name = request.getParameter("name"); output=response.getWriter(); Thread. } e.printStackTrace(); } output.write(name); }} 這三種方法都對解決servlet線程安全起到很好的作用,但我們如果對他們進行比較一下,看哪一種更適合呢: 第一個方案中:實現SingleThreadModel接口,Servlet引擎將為每個客戶請求都生成一個Servlet實例,這將引起大量的系統開銷,在新版本的Servlet2.4中也不提倡使用了。 第二個方案中:在程序中使用同步來保護要使用的共享數據,也使系統的性能大大的下降,這是因為被同步的代碼在同一時刻只能由一個線程來執行,使得同時處理其他客戶請求的吞吐量大大降低,大量客戶處于阻塞狀態,這對于并發用戶請求來說并非是一件很好的事情。另外為了保持主內存與工作內存數據的一致性要頻繁地刷新緩存,這也大大降低了系統性能,所以這種方案不大可取。 第三個方案則應該是最優方案:從JAVA內存模型來看,方法中的臨時變量都是在棧中分配空間,而每個線程都有自己的私有棧空間,互不干擾,不會影響性能,也不會產生線程安全的問題。 |
package TestFile;
import java.io.File;
import java.io.FileFilter;
/**
* @author 王業平
* 用于過濾以.bak結尾或包含.bak的文件
* 返回值的含義是 當包含該字符串時返回true
*/
public class ListFilter implements FileFilter{
@Override
public boolean accept(File file) {
//測試指定的文件(夾)是否應該包含在指定的列表中(就是測定作為過濾的條件是否滿足)
/*
* 如果是目錄的話,直接返回true 表示是滿足條件的一情況
*/
if(file.isDirectory()) return true;
/*
* 如果不是目錄的話,通過判斷在其名字里是否含有規定的字符,
* 因為string的index方法在不滿足條件(不含有指定的字符)是返回-1
* 所以以此來確定是否滿足條件
*/
String name=file.getName();
/*
* int index=name.indexOf(".bak");
* return index!=-1;
* 這種方法不安全,可能會刪除文件名中還含有.bak的文件,備份文件還可以用.BAK結尾
*/
return name.endsWith(".bak")||name.endsWith(".BAK");
}
}
使用此類
package TestFile;
import java.io.File;
/**
* @author Administrator
* 涉及到遞歸調用
*/
public class BakDelete{
public static void main(String[] args){
BakDelete bd=new BakDelete();
bd.listBakFile(new File("E:\\"));
}
public void listBakFile(File file){
File[] fs=file.listFiles(new ListFilter());
for(int i=0;i<fs.length;i++){
if(fs[i].isFile()){
System.out.println(fs[i].getAbsolutePath());//打印文件絕對路徑
fs[i].delete();
}else{
//System.out.println(fs[i].getAbsolutePath());
listBakFile(fs[i]);
}
}
//System.out.println(fs.length);
}
}