❶ java線程傳值的問題
把那些對象類型的變數定義為 static 類型
或者,有一個線程間傳值得方法,管道技術,不知道你有沒有接觸這方面的內容:
Java中利用管道實現線程間的通訊
管道(pipe)流是一種特殊的流,用於在不同線程(threads)間直接傳送數據。一個線程發送數據到輸出管道,另一個線程從輸入管道中讀數據。通過使用管道,實現不同線程間的通訊。
你可以搜艘縣官的內容,相信對你有幫助
❷ Java 如何創建100個Thread 線程
「創建100個線程」和「創建1個線程」是一樣的。
(如果不一樣,只可能是你問得唐突、不清晰)
你可以把100個線程放到一個數組中。
Thread threads[]=new Thread[100];
//然後逐個生成啟動
for(int i=0;i<100;i++){
threads[i]=new Thread(//put some runnable here );
threads[i].start();
}
❸ 如何用Java編寫多線程
在java中要想實現多線程,有兩種手段,一種是繼續Thread類,另外一種是實現Runable介面。
對於直接繼承Thread的類來說,代碼大致框架是:
?
123456789101112 class 類名 extends Thread{ 方法1; 方法2; … public void run(){ // other code… } 屬性1; 屬性2; … }
先看一個簡單的例子:
?
/** * @author Rollen-Holt 繼承Thread類,直接調用run方法 * */class hello extends Thread { public hello() { } public hello(String name) { this.name = name; } public void run() { for (int i = 0; i < 5; i++) { System.out.println(name + "運行 " + i); } } public static void main(String[] args) { hello h1=new hello("A"); hello h2=new hello("B"); h1.run(); h2.run(); } private String name; }
【運行結果】:
A運行 0
A運行 1
A運行 2
A運行 3
A運行 4
B運行 0
B運行 1
B運行 2
B運行 3
B運行 4
我們會發現這些都是順序執行的,說明我們的調用方法不對,應該調用的是start()方法。
當我們把上面的主函數修改為如下所示的時候:
?
123456 public static void main(String[] args) { hello h1=new hello("A"); hello h2=new hello("B"); h1.start(); h2.start(); }
然後運行程序,輸出的可能的結果如下:
A運行 0
B運行 0
B運行 1
B運行 2
B運行 3
B運行 4
A運行 1
A運行 2
A運行 3
A運行 4
因為需要用到CPU的資源,所以每次的運行結果基本是都不一樣的,呵呵。
注意:雖然我們在這里調用的是start()方法,但是實際上調用的還是run()方法的主體。
那麼:為什麼我們不能直接調用run()方法呢?
我的理解是:線程的運行需要本地操作系統的支持。
如果你查看start的源代碼的時候,會發現:
?
1234567891011121314151617 public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0 || this != me) throw new IllegalThreadStateException(); group.add(this); start0(); if (stopBeforeStart) { stop0(throwableFromStop); } } private native void start0();
注意我用紅色加粗的那一條語句,說明此處調用的是start0()。並且這個這個方法用了native關鍵字,次關鍵字表示調用本地操作系統的函數。因為多線程的實現需要本地操作系統的支持。
但是start方法重復調用的話,會出現java.lang.IllegalThreadStateException異常。
通過實現Runnable介面:
大致框架是:
?
123456789101112 class 類名 implements Runnable{ 方法1; 方法2; … public void run(){ // other code… } 屬性1; 屬性2; … }
來先看一個小例子吧:
?
2930 /** * @author Rollen-Holt 實現Runnable介面 * */class hello implements Runnable { public hello() { } public hello(String name) { this.name = name; } public void run() { for (int i = 0; i < 5; i++) { System.out.println(name + "運行 " + i); } } public static void main(String[] args) { hello h1=new hello("線程A"); Thread demo= new Thread(h1); hello h2=new hello("線程B"); Thread demo1=new Thread(h2); demo.start(); demo1.start(); } private String name; }
【可能的運行結果】:
線程A運行 0
線程B運行 0
線程B運行 1
線程B運行 2
線程B運行 3
線程B運行 4
線程A運行 1
線程A運行 2
線程A運行 3
線程A運行 4
關於選擇繼承Thread還是實現Runnable介面?
其實Thread也是實現Runnable介面的:
?
12345678 class Thread implements Runnable { //… public void run() { if (target != null) { target.run(); } } }
其實Thread中的run方法調用的是Runnable介面的run方法。不知道大家發現沒有,Thread和Runnable都實現了run方法,這種操作模式其實就是代理模式。關於代理模式,我曾經寫過一個小例子呵呵,大家有興趣的話可以看一下:http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144847.html
Thread和Runnable的區別:
如果一個類繼承Thread,則不適合資源共享。但是如果實現了Runable介面的話,則很容易的實現資源共享。
?
/** * @author Rollen-Holt 繼承Thread類,不能資源共享 * */class hello extends Thread { public void run() { for (int i = 0; i < 7; i++) { if (count > 0) { System.out.println("count= " + count--); } } } public static void main(String[] args) { hello h1 = new hello(); hello h2 = new hello(); hello h3 = new hello(); h1.start(); h2.start(); h3.start(); } private int count = 5; }
【運行結果】:
count= 5
count= 4
count= 3
count= 2
count= 1
count= 5
count= 4
count= 3
count= 2
count= 1
count= 5
count= 4
count= 3
count= 2
count= 1
大家可以想像,如果這個是一個買票系統的話,如果count表示的是車票的數量的話,說明並沒有實現資源的共享。
我們換為Runnable介面:
?
12345678910111213141516171819 /** * @author Rollen-Holt 繼承Thread類,不能資源共享 * */class hello implements Runnable { public void run() { for (int i = 0; i < 7; i++) { if (count > 0) { System.out.println("count= " + count--); } } } public static void main(String[] args) { hello he=new hello(); new Thread(he).start(); } private int count = 5; }
【運行結果】:
count= 5
count= 4
count= 3
count= 2
count= 1
總結一下吧:
實現Runnable介面比繼承Thread類所具有的優勢:
1):適合多個相同的程序代碼的線程去處理同一個資源
2):可以避免java中的單繼承的限制
3):增加程序的健壯性,代碼可以被多個線程共享,代碼和數據獨立。
所以,本人建議大家勁量實現介面。
?
❹ java 根據線程名字查詢一個線程,能實現嗎
根據線程名稱找到線程,在java中是可以實現的,實現步驟是:
1、首先獲取Java VM中當前運行的所有線程
以下代碼是用數組返回Java VM中當前運行的所有線程
publicstaticThread[]findAllThreads()
{
ThreadGroupgroup=Thread.currentThread().getThreadGroup();
ThreadGrouptopGroup=group;
/*遍歷線程組樹,獲取根線程組*/
while(group!=null)
{
topGroup=group;
group=group.getParent();
}
/*激活的線程數加倍*/
intestimatedSize=topGroup.activeCount()*2;
Thread[]slackList=newThread[estimatedSize];
/*獲取根線程組的所有線程*/
intactualSize=topGroup.enumerate(slackList);
/*intoalistthatistheexactsize*/
Thread[]list=newThread[actualSize];
System.array(slackList,0,list,0,actualSize);
return(list);
}
2、遍歷線程,比對名稱,找到需要尋找的線程
以下代碼可得到線程的名稱
Stringname=thread.getName();
❺ 怎樣分析 JAVA 的 Thread Dumps
當有障礙,或者是一個基於 JAVA 的 WEB 應用運行的比預期慢的時候,我們需要使用 thread mps。如果對於你來說,thread mps 是非常復雜的,這篇文章或許能對你有所幫助。在這里我將解釋在 JAVA 中什麼是 threads,他們的類型,怎麼被創建的,怎樣管理它們,你怎樣從正在運行的應用中 mp threads,最後你可以怎樣分析它以及確定瓶頸或者是阻塞線程。本文來自於 JAVA 應用程序長期調試經驗的結果。
Java and Thread
一個 web 伺服器使用幾十到幾百個線程來處理大量並發用戶,如果一個或多個線程使用相同的資源,線程之間的競爭就不可避免了,並且有時候可能會發生死鎖。
Thread contention 是一個線程等待鎖的一個狀態,這個鎖被另外一個線程持有,等待被釋放,不同的線程頻繁訪問 WEB 應用的共享資源。例如,記錄一條日誌,線程嘗試記錄日誌之前必須先獲取鎖來訪問共享資源。
死鎖是線程競爭的一個特殊狀態,一個或是多個線程在等待其他線程完成它們的任務為了完成它們自己的任務。
線程競爭會引起各種不同的問題,為了分析這些這些問題,你需要使用 mp threads,mp threads 能給你提供每個線程的精確狀態信息。
JAVA 線程的背景資料
線程同步
一個線程可以與其他線程在同一時間內被處理。為了確保一致性,當多個線程試圖使用共享資源的時候,通過使用 hread synchronization 在同一時間內,應該只有一個線程能訪問共享資源
JAVA 中的線程同步可以使用監視器,每個 JAVA 對象都有一個單獨的監視器,這個監視器僅僅只能被一個線程擁有,對於擁有一個由不同的線程所擁有的監視器的線程,確實需要在隊列中等待,以便其他線程釋放它的監視器。
線程狀態
為了分析一個 thread mp 文件,你需要知道線程狀態。線程情況在 java.lang.Thread.State 中闡明了。
當使用 java.lang.Thread 對象創建線程的時候,線程被命名為 Thread-(Number) 。當使用 java.util.concurrent.DefaultThreadFactory 對象創建線程的時候,線程被命名為 named pool-(Number)-thread-(Number)。當為應用程序分析成百上千的線程的時候,如果線程依然用它們默認的名字,分析它們將變得非常困難,因為這是非常難以辨別這些線程來分析的。
因此,你被建議開發一個命名線程的規則當一個新線程被創建的時候。
當你使用 java.lang.Thread 創建線程,你可以通過創建參數給該線程定義個約定俗成的名字。
public Thread(Runnable target, String name);
public Thread(ThreadGroup group, String name);
public Thread(ThreadGroup group, Runnable target, String name);
public Thread(ThreadGroup group, Runnable target, String name, long stackSize);
當你使用 java.util.concurrent.ThreadFactory 創建線程的時候,你可以通過生成你自己的線程工廠來命名它,如果你不需要特別的功能性,你可以使用 MyThreadFactory 作為以下描述:
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class MyThreadFactory implements ThreadFactory {
private static final ConcurrentHashMap<String, AtomicInteger> POOL_NUMBER =
new ConcurrentHashMap<String, AtomicInteger>();
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public MyThreadFactory(String threadPoolName) {
if (threadPoolName == null) {
throw new NullPointerException("threadPoolName");
}
POOL_NUMBER.putIfAbsent(threadPoolName, new AtomicInteger());
SecurityManager securityManager = System.getSecurityManager();
group = (securityManager != null) ? securityManager.getThreadGroup() :
Thread.currentThread().getThreadGroup();
AtomicInteger poolCount = POOL_NUMBER.get(threadPoolName);
if (poolCount == null) {
namePrefix = threadPoolName + " pool-00-thread-";
} else {
namePrefix = threadPoolName + " pool-" + poolCount.getAndIncrement() + "-thread-";
}
}
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(group, runnable, namePrefix + threadNumber.getAndIncrement(), 0);
if (thread.isDaemon()) {
thread.setDaemon(false);
}
if (thread.getPriority() != Thread.NORM_PRIORITY) {
thread.setPriority(Thread.NORM_PRIORITY);
}
return thread;
}
}
使用 MBean 獲取更多的細節信息
你可以使用 MBean 來獲取 ThreadInfo 對象。你也可以獲取更加多通過 thread mps 不能獲取的信息。通過使用 ThreadInfo。
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
long[] threadIds = mxBean.getAllThreadIds();
ThreadInfo[] threadInfos =
mxBean.getThreadInfo(threadIds);
for (ThreadInfo threadInfo : threadInfos) {
System.out.println(
threadInfo.getThreadName());
System.out.println(
threadInfo.getBlockedCount());
System.out.println(
threadInfo.getBlockedTime());
System.out.println(
threadInfo.getWaitedCount());
System.out.println(
threadInfo.getWaitedTime());
}
你可以使用方法 ThreadInfo 來提取阻塞線程或者是等待線程花費的時間。並利用這一點,你也可以得到那些處於非活動狀態的時間異常長的線程列表。
❻ java線程與操作系統線程
java線程管理是JVM的一部分,雖然大部分JVM直接映射java線程到底層系統線程,但是還是java的線程管理決定誰有機會運行
The thread scheler is the part of the JVM (although most JVMs map Java threads directly to native threads on the underlying OS) that decides which thread should run at any given moment, and also takes threads out of the run state. Assuming a single processor machine, only one thread can actually run at a time. Only one stack can ever be executing at one time. And it's the thread scheler that decides which thread—of all that are eligible—will actually run.
❼ java中Thread類有哪些主要成員變數
classThreadimplementsRunnable{
/*<clinit>does.*/
();
static{
registerNatives();
}
privatecharname[];
privateintpriority;
privateThreadthreadQ;
privatelongeetop;
privatebooleanstarted;//
/*Whetherornottosingle_stepthisthread.*/
privatebooleansingle_step;
/*.*/
privatebooleandaemon=false;
/*.*/
privatebooleanstillborn=false;
/*Whatwillberun.*/
privateRunnabletarget;
/*Thegroupofthisthread*/
privateThreadGroupgroup;
/**/
;
/**/
;
/*.*/
;
/*.Thismapismaintained
*bytheThreadLocalclass.*/
ThreadLocal.ThreadLocalMapthreadLocals=null;
/*
*Inheritable.Thismapis
*.
*/
ThreadLocal.=null;
/*
*,or0ifthecreatordid
*notspecifyastacksize.ItisuptotheVMtodowhateverit
*likeswiththisnumber;someVMswillignoreit.
*/
privatelongstackSize;
/*
*ThreadID
*/
privatelongtid;
/*ForgeneratingthreadID*/
;
/*Javathreadstatusfortools,
*initializedtoindicatethread'notyetstarted'
*/
privateintthreadStatus=0;
(){
return++threadSeqNumber;
}
/*/O
*operation,ifany.Theblocker'
*aftersettingthisthread'sinterruptstatus.
*/
;
privateObjectblockerLock=newObject();
/*Settheblockerfield;invokedviasun.misc.SharedSecretsfromjava.niocode
*/
voidblockedOn(Interruptibleb){
synchronized(blockerLock){
blocker=b;
}
}
/**
*.
*/
publicfinalstaticintMIN_PRIORITY=1;
/**
*.
*/
publicfinalstaticintNORM_PRIORITY=5;
/**
*.
*/
publicfinalstaticintMAX_PRIORITY=10;
❽ Java線程 Java線程
Java Thread sleep示例
這里是一個簡單的程序,它使用Thread.sleep()暫停主線程2分鍾。
[java] view plain
package com.journaldev.threads;
public class ThreadSleep {
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(2000);
System.out.println("Sleep time in ms = "+(System.currentTimeMillis()-start));
}
}
如果你將執行上面的程序,你將注意到線程休眠列印時間略微大於2000毫秒,導致線程這樣執行的原因是操作系統具體實現和線程調度引起的。
Java線程休眠要點:
1.它總是暫停當前執行的線程
2.實際休眠的線程在喚醒開始執行前依賴於系統定時器和調度器,對於一個平穩的系統來住,線程實際執行的時間接近於指定線程休眠時間,但是對於一個忙碌的系統來說它將稍微超出一些。
3.當線程休眠時不會丟失已經獲得的監控和鎖。
4.任何線程都能中斷當前休眠的線程,將導致InterruptedException異常拋出。
線程休眠是如何工作的:
Thread.sleep()與線程調度器交互,在指定的時間內將當前線程作為等待狀態放入,一旦等待時間結束後,線程狀態變為可運行狀態,並等待CPU進一步執行。所以當前線程的實際休眠時間依賴於線程調度器和一部門操作系統。
❾ java fork join和thread的區別
Java並發編程的4種風格:Threads,Executors,ForkJoin和Actors
我們生活在一個事情並行發生的世界。自然地,我們編寫的程序也反映了這個特點,它們可以並發的執行。當然除了Python代碼(譯者註:鏈接裡面講述了Python的全局解釋器鎖,解釋了原因),不過你仍然可以使用Jython在JVM上運行你的程序,來利用多處理器電腦的強大能力。
然而,並發程序的復雜程度遠遠超出了人類大腦的處理能力。相比較而言,我們簡直弱爆了:我們生來就不是為了思考多線程程序、評估並發訪問有限資源以及預測哪裡會發生錯誤或者瓶頸。
面對這些困難,人類已經總結了不少並發計算的解決方案和模型。這些模型強調問題的不同部分,當我們實現並行計算時,可以根據問題做出不同的選擇。
在這篇文章中,我將會用對同一個問題,用不同的代碼來實現並發的解決方案;然後討論這些方案有哪些好的地方,有哪些缺陷,可能會有什麼樣的陷阱在等著你。
我們將介紹下面幾種並發處理和非同步代碼的方式:
• 裸線程
• Executors和Services
• ForkJoin框架和並行流
• Actor模型
為了更加有趣一些,我沒有僅僅通過一些代碼來說明這些方法,而是使用了一個共同的任務,因此每一節中的代碼差不多都是等價的。另外,這些代碼僅僅是展示用的,初始化的代碼並沒有寫出來,並且它們也不是產品級的軟體示例。
對了,最後一件事:在文章最後,有一個小調查,關於你或者你的組織正在使用哪種並發模式。為了你的工程師同胞們,請填一下調查!
任務
任務:實現一個方法,它接收一條消息和一組字元串作為參數,這些字元串與某個搜索引擎的查詢頁面對應。對每個字元串,這個方法發出一個http請求來查詢消息,並返回第一條可用的結果,越快越好。
如果有錯誤發生,拋出一個異常或者返回空都是可以的。我只是嘗試避免為了等待結果而出現無限循環。
簡單說明:這次我不會真正深入到多線程如何通訊的細節,或者深入到Java內存模型。如果你迫切地想了解這些,你可以看我前面的文章利用JCStress測試並發。
那麼,讓我們從最直接、最核心的方式來在JVM上實現並發:手動管理裸線程。
方法1:使用「原汁原味」的裸線程
解放你的代碼,回歸自然,使用裸線程!線程是並發最基本的單元。Java線程本質上被映射到操作系統線程,並且每個線程對象對應著一個計算機底層線程。
自然地,JVM管理著線程的生存期,而且只要你不需要線程間通訊,你也不需要關注線程調度。
每個線程有自己的棧空間,它佔用了JVM進程空間的指定一部分。
線程的介面相當簡明,你只需要提供一個Runnable,調用.start()開始計算。沒有現成的API來結束線程,你需要自己來實現,通過類似boolean類型的標記來通訊。