java.lang.Thread
Java'da nasıl öldürürsün ?
ExecutorStatus
: stackoverflow.com/questions/2275443/how-to-timeout-a-thread
java.lang.Thread
Java'da nasıl öldürürsün ?
ExecutorStatus
: stackoverflow.com/questions/2275443/how-to-timeout-a-thread
Yanıtlar:
Sun'ın neden kullanımdan kaldırıldığına dairThread.stop()
bu konuya bakın . Bunun neden kötü bir yöntem olduğu ve genel olarak konuları güvenli bir şekilde durdurmak için ne yapılması gerektiği hakkında ayrıntılara girer.
Önerdikleri yol, arka plan iş parçacığının durmasını isteyen bir bayrak olarak paylaşılan bir değişken kullanmaktır. Bu değişken daha sonra iş parçacığının sonlandırılmasını isteyen farklı bir nesne tarafından ayarlanabilir.
getConnection()
den java.sql.DriverManager
. Bağlantı girişimi çok uzun sürerse, karşılık gelen iş parçacığını arayarak öldürmeye çalışırım Thread.interrupt()
ama iş parçacığını hiç etkilemez. Ancak Thread.stop()
eserler, eğer işe interrupt()
yaramazsa çalışmaması gerektiğini söylüyor . Nasıl çalıştığını merak ediyorum ve kullanımdan kaldırılmış yöntemi kullanmaktan kaçının.
Genellikle yapmazsınız ..
Thread.interrupt () (javadoc link) kullanarak ne yapıyorsa onu kesmesini istersiniz.
Javadoc'un neden burada olduğuna dair iyi bir açıklama (java technote link)
interrupt()
Yöntem çağrıldığında Thread bağlamına ne olur ? Ana soru, her yeni evre için günlük oluşturma ile ilgilidir .
Java'da iş parçacıkları öldürülmez, ancak bir iş parçacığının durdurulması işbirlikçi bir şekilde yapılır . İş parçacığının sonlandırılması istenir ve iş parçacığı daha sonra düzgün bir şekilde kapanabilir.
Genellikle bir volatile boolean
, ilgili değere ayarlandığında dişin periyodik olarak kontrol ettiği ve sonlandığı alan kullanılır.
Ben bir iş parçacığı sonlanması gerektiğini kontrol etmek için kullanmak olmaz . Eğer kullanırsanız bir saha düzenleyici olarak, bu güvenilir çalışacaktır, ancak kod yerine içeride başka engelleme yöntemleri kullanır için, daha karmaşık hale gelirse döngü, kod edeceğini, meydana gelebilecek sonlandırmak değil hiç ya da en azından daha uzun sürer senin kadar belki ister.boolean
volatile
while
Belirli engelleme kitaplığı yöntemleri kesintiyi destekler.
Her iş parçacığının zaten bir boole bayrağı kesilmiş durumu vardır ve bundan yararlanmalısınız. Bu şekilde uygulanabilir:
public void run() {
try {
while (!interrupted()) {
// ...
}
} catch (InterruptedException consumed)
/* Allow thread to exit */
}
}
public void cancel() { interrupt(); }
Uygulamada Java Concurrency'dan uyarlanan kaynak kodu . cancel()
Yöntem herkese açık olduğundan, başka bir iş parçacığının bu yöntemi istediğiniz gibi çağırmasına izin verebilirsiniz.
Bunun bir yolu, bir sınıf değişkeni ayarlamak ve onu bir sentinel olarak kullanmaktır.
Class Outer {
public static volatile flag = true;
Outer() {
new Test().start();
}
class Test extends Thread {
public void run() {
while (Outer.flag) {
//do stuff here
}
}
}
}
Harici bir sınıf değişkeni ayarlayın, yani yukarıdaki örnekte flag = true. İş parçacığını 'öldürmek' için false olarak ayarlayın.
volatile
her yerde düzgün çalışmasını sağlamak için "bayrak" yapın. İç sınıf statik değildir, bu nedenle bayrak bir örnek değişkeni olmalıdır. Diğer işlemlerin (kesme gibi) yapılabilmesi için bayrak bir erişimci yönteminde temizlenmelidir. "Bayrak" adı açıklayıcı değil.
Bunu yapmanın bir yolu var. Ancak kullanmak zorundaysanız, ya kötü bir programcısınız ya da kötü programcılar tarafından yazılmış bir kod kullanıyorsunuz. Bu nedenle, kötü bir programcı olmayı bırakmayı veya bu kötü kodu kullanarak durdurmayı düşünmelisiniz. Bu çözüm yalnızca BAŞKA YOLLU OLMAYAN durumlar içindir.
Thread f = <A thread to be stopped>
Method m = Thread.class.getDeclaredMethod( "stop0" , new Class[]{Object.class} );
m.setAccessible( true );
m.invoke( f , new ThreadDeath() );
Thread.stop
kullanımdan kaldırılsa bile halkı aramak hala mümkündür .
Thread.stop
de aynısını yapar, ancak erişimi ve izinleri de denetler. Kullanımı Thread.stop
oldukça açık ve Thread.stop0
bunun yerine neden kullandığımı hatırlamıyorum . Belki Thread.stop
benim özel durumumda işe yaramadı (Java 6'da Weblogic). Ya da belki Thread.stop
de kullanımdan kaldırılmıştır ve uyarıya neden olur.
Biriken yorumlara dayanarak birkaç gözlem eklemek istiyorum.
Thread.stop()
güvenlik yöneticisi izin verirse bir iş parçacığını durduracaktır.Thread.stop()
tehlikeli. Bir JEE ortamında çalışıyorsanız ve çağıran kod üzerinde herhangi bir kontrole sahip değilseniz, gerekli olabilir; bkz Thread.stop kullanımdan kaldırıldı Neden?stop()
çağıran evrede yeni bir ThreadDeathError
hata oluşturur ve bu hatayı hedef evreye atar . Bu nedenle, yığın izlemesi genellikle değersizdir.stop()
güvenlik yöneticisine danışır ve ardından stop1()
bu çağrıları arar stop0()
. stop0()
yerel koddur.Thread.stop()
itibaren henüz kaldırılmadı (ancak), ancak Thread.stop(Throwable)
Java 11'de kaldırıldı. ( Posta listesi , JDK-8204243 )Oy verirdim Thread.stop()
.
Örneğin, uzun süreli bir işleminiz var (bir ağ isteği gibi). Sözde bir yanıt bekliyorsunuz, ancak bu zaman alabilir ve kullanıcı diğer kullanıcı arayüzüne geçebilir. Bu bekleyen iş parçacığı artık a) işe yaramaz b) potansiyel bir sorun çünkü sonuç alacağı zaman, tamamen işe yaramaz ve hata sayısına yol açabilecek geri aramaları tetikler.
Tüm bunlar ve CPU yoğun olabilecek yanıt işleme yapabilir. Ve bir geliştirici olarak siz bile durduramazsınız, çünkü atamazsınızif (Thread.currentThread().isInterrupted())
tüm kodlara satır atamazsınız.
Yani bir ipliği zorla durduramama tuhaf.
Thread.stop()
yine de güvenli bir şekilde arama yapamazsınız . Oy vermiyorsunuz Thread.stop()
, güvenli bir şekilde kürtajlı hale gelmesi uzun zaman alabilecek her operasyonu gerçekleştiren herkesten isteniyorsunuz. Ve bu iyi bir fikir olabilir, ancak Thread.stop()
güvenli kürtaj talep etmenin bir yolu olarak uygulamakla hiçbir ilgisi yoktur . Bunun interrupt
için zaten var .
stop
.
Soru oldukça belirsiz. “Bir programın bir iş parçacığının çalışmasını durdurması için nasıl yazacağımı” kastediyorsanız, diğer çeşitli yanıtlar yardımcı olacaktır. Ancak “Şu anda yeniden başlatamadığım bir sunucu ile acil durumum var ve sadece ölmek için belirli bir iş parçacığına ihtiyacım var, ne gelebilir” demek istediyseniz, izleme araçlarını eşleştirmek için bir müdahale aracına ihtiyacınız vardır jstack
.
Bu amaçla jkillthread'i yarattım . Kullanım talimatlarına bakınız.
Tabii ki tamamen güvenilmeyen bir kod çalıştırdığınız bir durum var. (Kişisel olarak yüklenen komut dosyalarının Java ortamımda yürütülmesine izin vererek bunu yaptım. Evet, her yerde çalan güvenlik alarm zili var, ancak uygulamanın bir parçası.) Bu talihsiz örnekte, öncelikle senaryo yazarlarına sorarak umutlu oluyorsunuz. bir tür boolean run / don't-run sinyaline saygı göstermek. Tek iyi başarısız güvenli, iş parçacığı üzerinde durdurma yöntemini çağırmak, örneğin, biraz zaman aşımından daha uzun çalışırsa.
Ancak, bu sadece "iyi" ve mutlak değil, çünkü kod ThreadDeath hatasını (veya açıkça attığınız istisnayı) yakalayabilir ve centilmence bir iş parçacığının yapması gerektiği gibi geri alamaz. Yani, sonuçta AFAIA mutlak başarısız güvenli yoktur.
Bir iş parçacığını incelikle öldürmenin bir yolu yoktur.
İş parçacığını kesmeye çalışabilirsiniz, bir müşterek stratejisi, iş parçacığının kendisini durduracağını bildirmek için bir zehir hapı kullanmaktır
public class CancelSupport {
public static class CommandExecutor implements Runnable {
private BlockingQueue<String> queue;
public static final String POISON_PILL = “stopnow”;
public CommandExecutor(BlockingQueue<String> queue) {
this.queue=queue;
}
@Override
public void run() {
boolean stop=false;
while(!stop) {
try {
String command=queue.take();
if(POISON_PILL.equals(command)) {
stop=true;
} else {
// do command
System.out.println(command);
}
} catch (InterruptedException e) {
stop=true;
}
}
System.out.println(“Stopping execution”);
}
}
}
BlockingQueue<String> queue=new LinkedBlockingQueue<String>();
Thread t=new Thread(new CommandExecutor(queue));
queue.put(“hello”);
queue.put(“world”);
t.start();
Thread.sleep(1000);
queue.put(“stopnow”);
Genellikle bir iş parçacığını öldürmez, durdurmaz ya da kesmezsiniz (ya da kesik olup olmadığını kontrol edersiniz ()), ancak doğal olarak sonlanmasına izin verirsiniz.
Basit. İş parçacığının etkinliğini denetlemek için run () yönteminin içindeki (uçucu) boole değişkeniyle birlikte herhangi bir döngüyü kullanabilirsiniz. Durdurmak için etkin iş parçacığından ana iş parçacığına da dönebilirsiniz.
Bu şekilde bir ipliği incelikle öldürürsün :).
Ani iş parçacığı sonlandırma girişimleri iyi bilinen kötü programlama uygulaması ve kötü uygulama tasarımının kanıtıdır. Çok iş parçacıklı uygulamadaki tüm iş parçacıkları açıkça ve dolaylı olarak aynı işlem durumunu paylaşır ve tutarlı kalması için birbirleriyle işbirliği yapmaya zorlanır, aksi takdirde başvurunuz gerçekten teşhis edilmesi zor olan hatalara eğilimlidir. Bu nedenle, dikkatli ve açık bir uygulama tasarımı ile bu tür bir tutarlılığın güvencesini sağlamak geliştiricinin sorumluluğundadır.
Kontrollü diş sonlandırmaları için iki ana doğru çözüm vardır:
Ani iplik sonlandırmayla ilgili sorunların iyi ve ayrıntılı açıklaması ve kontrollü iplik sonlandırması için yanlış ve doğru çözüm örnekleri burada bulunabilir:
İşte konuyla ilgili birkaç iyi okuma:
Android'de çalışmak için kesinti alamadım, bu yüzden bu yöntemi kullandım, mükemmel çalışıyor:
boolean shouldCheckUpdates = true;
private void startupCheckForUpdatesEveryFewSeconds() {
Thread t = new Thread(new CheckUpdates());
t.start();
}
private class CheckUpdates implements Runnable{
public void run() {
while (shouldCheckUpdates){
//Thread sleep 3 seconds
System.out.println("Do your thing here");
}
}
}
public void stop(){
shouldCheckUpdates = false;
}
'Bir iş parçacığını öldürmek' kullanılacak doğru ifade değildir. İşte irade üzerinde iş parçacığının zarif tamamlama / çıkış uygulamak bir yolu:
Çalıştırdığım runnable:
class TaskThread implements Runnable {
boolean shouldStop;
public TaskThread(boolean shouldStop) {
this.shouldStop = shouldStop;
}
@Override
public void run() {
System.out.println("Thread has started");
while (!shouldStop) {
// do something
}
System.out.println("Thread has ended");
}
public void stop() {
shouldStop = true;
}
}
Tetikleyici sınıf:
public class ThreadStop {
public static void main(String[] args) {
System.out.println("Start");
// Start the thread
TaskThread task = new TaskThread(false);
Thread t = new Thread(task);
t.start();
// Stop the thread
task.stop();
System.out.println("End");
}
}
Thread.stop kullanımdan kaldırıldı, bu yüzden java'da bir iş parçacığını nasıl durdurabiliriz?
İptal isteğinde bulunmak için her zaman kesme yöntemini ve geleceği kullanın
Callable < String > callable = new Callable < String > () {
@Override
public String call() throws Exception {
String result = "";
try {
//assume below take method is blocked as no work is produced.
result = queue.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return result;
}
};
Future future = executor.submit(callable);
try {
String result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
logger.error("Thread timedout!");
return "";
} finally {
//this will call interrupt on queue which will abort the operation.
//if it completes before time out, it has no side effects
future.cancel(true);
}
public interface CustomCallable < T > extends Callable < T > {
void cancel();
RunnableFuture < T > newTask();
}
public class CustomExecutorPool extends ThreadPoolExecutor {
protected < T > RunnableFuture < T > newTaskFor(Callable < T > callable) {
if (callable instanceof CancellableTask)
return ((CancellableTask < T > ) callable).newTask();
else
return super.newTaskFor(callable);
}
}
public abstract class UnblockingIOTask < T > implements CustomCallable < T > {
public synchronized void cancel() {
try {
obj.close();
} catch (IOException e) {
logger.error("io exception", e);
}
}
public RunnableFuture < T > newTask() {
return new FutureTask < T > (this) {
public boolean cancel(boolean mayInterruptIfRunning) {
try {
this.cancel();
} finally {
return super.cancel(mayInterruptIfRunning);
}
}
};
}
}