Executor Service 스레드 및 스레드 풀 이름 지정
, ation들 the, 리 the the the the the the를 사용하는 .Executor
틀
Executors.newSingleThreadExecutor().submit(new Runnable(){
@Override
public void run(){
// do stuff
}
}
응용 이름으로 됩니다.Thread[pool-1-thread-1]
은 그다지 유용하지 만, 가 알 수 로는, 「다다다다」입니다」라고 하는 것입니다Executor
프레임워크에서는 작성된 스레드 또는 스레드 맵의 이름을 쉽게 지정할 수 없습니다.
그렇다면 스레드/스레드 풀의 이름을 어떻게 지정할 수 있을까요?를 들면, 「 」입니다.Thread[FooPool-FooThread]
.
구아바는 거의 항상 당신이 필요로 하는 것을 가지고 있다.
ThreadFactory namedThreadFactory =
new ThreadFactoryBuilder().setNameFormat("my-sad-thread-%d").build()
그리고 그것을 당신의 것들에게 전해주세요.ExecutorService
.
를 에 제공할 수 있습니다.공장에서는 스레드 작성을 담당하며 스레드 이름을 지정할 수 있습니다.
Javadoc 견적을 내려면:
새 스레드 작성
는 「」를 됩니다.
ThreadFactory
한, 「」는 「」입니다Executors.defaultThreadFactory()
하여 모든 스레드를 한 ""로ThreadGroup
같은 '일부러'를 가지고 있습니다.NORM_PRIORITY
및 statuspriority " non-time " 입니다. 것을 제공함으로써ThreadFactory
스레드의 이름, 스레드 그룹, 우선순위, 데몬 상태 등을 변경할 수 있습니다.「」의 'ThreadFactory
는, 「null」로부터 하는 것에 , 되었을 때에 합니다.newThread
진행되지만 수 있습니다.
자체 스레드 팩토리를 제공하면 적절한 이름으로 스레드를 작성할 수 있습니다.예를 들어 다음과 같습니다.
class YourThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
return new Thread(r, "Your name");
}
}
Executors.newSingleThreadExecutor(new YourThreadFactory()).submit(someRunnable);
아니면 코틀린에서
Executors.newSingleThreadExecutor { r -> Thread(r, "Your name") }
스레드가 실행되는 동안 나중에 스레드 이름을 변경할 수도 있습니다.
Thread.currentThread().setName("FooName");
예를 들어 다른 유형의 작업에 동일한 ThreadFactory를 사용하는 경우 이 기능이 유용할 수 있습니다.
from apache commons-lang은 명명 동작에도 도움이 됩니다.익명의 내부 클래스를 작성하는 대신, 작성기를 사용하여 스레드의 이름을 원하는 대로 지정할 수 있습니다.다음은 javadocs의 예입니다.
// Create a factory that produces daemon threads with a naming pattern and
// a priority
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("workerthread-%d")
.daemon(true)
.priority(Thread.MAX_PRIORITY)
.build();
// Create an executor service for single-threaded execution
ExecutorService exec = Executors.newSingleThreadExecutor(factory);
스프링을 사용하는 경우 스레드 이름 접두사를 설정할 수 있습니다.
예제:
ExecutorService alphaExecutor =
Executors.newFixedThreadPool(10, new CustomizableThreadFactory("alpha-"));
'하다, 하다, 하다, 하다'를 수도 있습니다.ExecutorService
스프링빈을 사용하여 - 그러면 모든 스레드의 이름이beanName-
프레픽스
@Bean
public ThreadPoolExecutorFactoryBean myExecutor() {
ThreadPoolExecutorFactoryBean executorFactoryBean = new ThreadPoolExecutorFactoryBean();
// configuration of your choice
return executorFactoryBean;
}
in in in in in 라는 이름이 붙습니다.myExecutor-
프레픽스프리픽스를 명시적으로 다른 값으로 설정할 수 있습니다(예: "myPool-"
설정별)executorFactoryBean.setThreadNamePrefix("myPool-")
공장용 콩으로요
Oracle에는 이를 위한 개방형 RFE가 있습니다.Oracle 직원의 코멘트를 보면 문제를 이해하지 못하고 수정되지 않는 것 같습니다.JDK에서 지원하는 것은 매우 간단하기 때문에(역호환성을 깨뜨리지 않고) RFE가 오해받는 것은 유감입니다.
지적한 바와 같이, 독자적인 Thread Factory를 실장할 필요가 있습니다.이 목적을 위해서만 Guava나 Apache Commons를 끌어당기고 싶지 않다면, 여기에 다음 정보를 제공합니다.ThreadFactory
사용할 수 있는 구현입니다.스레드명 프리픽스를 「풀」이 아닌 다른 것으로 설정하는 기능 이외에는, JDK 로부터 취득하는 것과 완전하게 비슷합니다.
package org.demo.concurrency;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* ThreadFactory with the ability to set the thread name prefix.
* This class is exactly similar to
* {@link java.util.concurrent.Executors#defaultThreadFactory()}
* from JDK8, except for the thread naming feature.
*
* <p>
* The factory creates threads that have names on the form
* <i>prefix-N-thread-M</i>, where <i>prefix</i>
* is a string provided in the constructor, <i>N</i> is the sequence number of
* this factory, and <i>M</i> is the sequence number of the thread created
* by this factory.
*/
public class ThreadFactoryWithNamePrefix implements ThreadFactory {
// Note: The source code for this class was based entirely on
// Executors.DefaultThreadFactory class from the JDK8 source.
// The only change made is the ability to configure the thread
// name prefix.
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
/**
* Creates a new ThreadFactory where threads are created with a name prefix
* of <code>prefix</code>.
*
* @param prefix Thread name prefix. Never use a value of "pool" as in that
* case you might as well have used
* {@link java.util.concurrent.Executors#defaultThreadFactory()}.
*/
public ThreadFactoryWithNamePrefix(String prefix) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup()
: Thread.currentThread().getThreadGroup();
namePrefix = prefix + "-"
+ poolNumber.getAndIncrement()
+ "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon()) {
t.setDaemon(false);
}
if (t.getPriority() != Thread.NORM_PRIORITY) {
t.setPriority(Thread.NORM_PRIORITY);
}
return t;
}
}
이 제품을 사용하고 싶을 때는 모든 것이Executors
독자적인 방법을 제공할 수 있습니다.ThreadFactory
.
이것.
Executors.newSingleThreadExecutor();
는 스레드 이름이 지정된 Executor Service를 제공합니다.pool-N-thread-M
그러나 을 사용하여
Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("primecalc"));
스레드 이름이 지정된 Executor Service가 제공됩니다.primecalc-N-thread-M
보일라!
다른 답변에서도 이미 언급했듯이, 고객님이 직접 구현하여 사용할 수 있습니다.java.util.concurrent.ThreadFactory
interface(외부 라이브러리 불필요)아래에 코드를 붙여넣는 이유는 이전 답변과 다르기 때문입니다.String.format
method 및 스레드의 기본 이름을 생성자 인수로 사용합니다.
import java.util.concurrent.ThreadFactory;
public class NameableThreadFactory implements ThreadFactory{
private int threadsNum;
private final String namePattern;
public NameableThreadFactory(String baseName){
namePattern = baseName + "-%d";
}
@Override
public Thread newThread(Runnable runnable){
threadsNum++;
return new Thread(runnable, String.format(namePattern, threadsNum));
}
}
다음은 사용 예를 제시하겠습니다.
ThreadFactory threadFactory = new NameableThreadFactory("listenerThread");
final ExecutorService executorService = Executors.newFixedThreadPool(5, threadFactory);
편집: 내 파일 만들기ThreadFactory
@mchernyakov가 지적해 준 덕분에 스레드 세이프가 구현됩니다.ThreadFactory
에는 그 세이프해야 .DefaultThreadFactory
스레드 세이프가 큰 힌트입니다.
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class NameableThreadFactory implements ThreadFactory{
private final AtomicInteger threadsNum = new AtomicInteger();
private final String namePattern;
public NameableThreadFactory(String baseName){
namePattern = baseName + "-%d";
}
@Override
public Thread newThread(Runnable runnable){
return new Thread(runnable, String.format(namePattern, threadsNum.addAndGet(1)));
}
}
a a a a a a a a a a a a를 사용하는 것입니다.Thread.currentThread().setName(myName);
run()
★★★★★★ 。
private class TaskThreadFactory implements ThreadFactory
{
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "TASK_EXECUTION_THREAD");
return t;
}
}
ThreadFactory를 실행 서비스에 전달하면 바로 사용할 수 있습니다.
Thread Factory 확장
public interface ThreadFactory
필요에 따라 새 스레드를 생성하는 개체입니다.스레드 팩토리를 사용하면, 새로운 스레드에의 콜의 하드 배선이 불필요하게 되어, 애플리케이션이 특수한 스레드 서브 클래스나 priority등을 사용할 수 있게 됩니다.
Thread newThread(Runnable r)
새 스레드를 구성합니다.또, 우선도, 이름, 데몬 상태, 스레드 그룹등을 초기화할 수도 있습니다.
샘플 코드:
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;
class SimpleThreadFactory implements ThreadFactory {
String name;
AtomicInteger threadNo = new AtomicInteger(0);
public SimpleThreadFactory (String name){
this.name = name;
}
public Thread newThread(Runnable r) {
String threadName = name+":"+threadNo.incrementAndGet();
System.out.println("threadName:"+threadName);
return new Thread(r,threadName );
}
public static void main(String args[]){
SimpleThreadFactory factory = new SimpleThreadFactory("Factory Thread");
ThreadPoolExecutor executor= new ThreadPoolExecutor(1,1,60,
TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(1),new ThreadPoolExecutor.DiscardPolicy());
final ExecutorService executorService = Executors.newFixedThreadPool(5,factory);
for ( int i=0; i < 100; i++){
executorService.submit(new Runnable(){
public void run(){
System.out.println("Thread Name in Runnable:"+Thread.currentThread().getName());
}
});
}
executorService.shutdown();
}
}
출력:
java SimpleThreadFactory
thread no:1
thread no:2
Thread Name in Runnable:Factory Thread:1
Thread Name in Runnable:Factory Thread:2
thread no:3
thread no:4
Thread Name in Runnable:Factory Thread:3
Thread Name in Runnable:Factory Thread:4
thread no:5
Thread Name in Runnable:Factory Thread:5
....기타
단일 스레드 실행자의 이름만 변경하고 싶다면 스레드 팩토리로 lamda를 사용하는 것이 가장 쉽습니다.
Executors.newSingleThreadExecutor(runnable -> new Thread(runnable, "Your name"));
Executors.default의 기존 기능 사용ThreadFactory() 단, 이름만 설정:
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class NamingThreadFactory implements ThreadFactory {
private final String prefix;
private final AtomicInteger threadNumber = new AtomicInteger(0);
public NamingThreadFactory(String prefix){
this.prefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setName(prefix + threadNumber.addAndGet(1));
return t;
}
}
(합니다).guava
: 라이브러리) :
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("SO-POOL-%d").build();
ExecutorService executorService = Executors.newFixedThreadPool(5,namedThreadFactory);
기존 공장을 꾸미는 데 사용하는 자체 개발 핵심 Java 솔루션:
public class ThreadFactoryNameDecorator implements ThreadFactory {
private final ThreadFactory defaultThreadFactory;
private final String suffix;
public ThreadFactoryNameDecorator(String suffix) {
this(Executors.defaultThreadFactory(), suffix);
}
public ThreadFactoryNameDecorator(ThreadFactory threadFactory, String suffix) {
this.defaultThreadFactory = threadFactory;
this.suffix = suffix;
}
@Override
public Thread newThread(Runnable task) {
Thread thread = defaultThreadFactory.newThread(task);
thread.setName(thread.getName() + "-" + suffix);
return thread;
}
}
동작 중:
Executors.newSingleThreadExecutor(new ThreadFactoryNameDecorator("foo"));
Executors.newSingleThreadExecutor(r -> new Thread(r, "someName")).submit(getJob());
Runnable getJob() {
return () -> {
// your job
};
}
위의 몇 가지 코멘트를 바탕으로 봤을 때 람다를 사용했을 뿐이라는 점이 다릅니다.
Executors.newFixedThreadPool(10, r -> new Thread(r, "my-threads-%d"))
예를 들어 기존 구현(기본값 등)을 사용하여 ThreadFactory의 구현을 직접 작성할 수 있습니다.ThreadFactory)를 선택하고 마지막에 이름을 변경합니다.
ThreadFactory 구현 예:
class ThreadFactoryWithCustomName implements ThreadFactory {
private final ThreadFactory threadFactory;
private final String name;
public ThreadFactoryWithCustomName(final ThreadFactory threadFactory, final String name) {
this.threadFactory = threadFactory;
this.name = name;
}
@Override
public Thread newThread(final Runnable r) {
final Thread thread = threadFactory.newThread(r);
thread.setName(name);
return thread;
}
}
용도:
Executors.newSingleThreadExecutor(new ThreadFactoryWithCustomName(
Executors.defaultThreadFactory(),
"customName")
);
이것은 스레드 덤프 분석기의 커스터마이즈된 이름을 제공하는 커스터마이즈된 공장입니다. 저는 ㅇㅇㅇㅇㅇㅇㅇㅇㅇ만 .tf=null
JVM 기본 스레드 팩토리를 재사용합니다.이 웹 사이트에는 더 고급 스레드 팩토리가 있습니다.
public class SimpleThreadFactory implements ThreadFactory {
private ThreadFactory tf;
private String nameSuffix;
public SimpleThreadFactory (ThreadFactory tf, String nameSuffix) {
this.tf = tf!=null ? tf : Executors.defaultThreadFactory();
this.nameSuffix = nameSuffix;
}
@Override public Thread newThread(Runnable task) {
// default "pool-1-thread-1" to "pool-1-thread-1-myapp-MagicTask"
Thread thread=tf.newThread(task);
thread.setName(thread.getName()+"-"+nameSuffix);
return thread;
}
}
- - - - -
ExecutorService es = Executors.newFixedThreadPool(4, new SimpleThreadFactory(null, "myapp-MagicTask") );
디버깅을 위한 스레드 덤프 루프입니다.
ThreadMXBean mxBean=ManagementFactory.getThreadMXBean();
long[] tids = mxBean.getAllThreadIds();
System.out.println("------------");
System.out.println("ThreadCount="+tids.length);
for(long tid : tids) {
ThreadInfo mxInfo=mxBean.getThreadInfo(tid);
if (mxInfo==null) {
System.out.printf("%d %s\n", tid, "Thread not found");
} else {
System.out.printf("%d %s, state=%s, suspended=%d, lockowner=%d %s\n"
, mxInfo.getThreadId(), mxInfo.getThreadName()
, mxInfo.getThreadState().toString()
, mxInfo.isSuspended()?1:0
, mxInfo.getLockOwnerId(), mxInfo.getLockOwnerName()
);
}
}
몇 가지 간단한 예를 들어 보겠습니다.옵션도 준비되어 있습니다.
고유 번호(이것도 메서드에 넣을 수 있음):
AtomicInteger threadNum = new AtomicInteger(0);
ExecutorService e = Executors.newSingleThreadExecutor(r -> new Thread(r, "my-name-" + threadNum.incrementAndGet()));
고유 번호 및 "아마도" 고유 이름(새로운 실행 가능 개체를 생성하는 경우)스레드 시작을 두 번 이상 호출된 메서드 내에서 수행하는 경우 다음과 같이 유용합니다.
AtomicInteger threadNum = new AtomicInteger(0);
ExecutorService e = Executors.newSingleThreadExecutor(r -> new Thread(r, "my-name-" + threadNum.incrementAndGet() + "-" + r.hashCode()));
static var가 있는 클래스가 필요할 때마다 원하는 이름을 원하는 경우(또한 여기에 정적 풀 번호 접두사를 추가할 수도 있음), 다른 답변을 참조하십시오.
및 JDK < 8 (새로운 클래스가 필요 없거나 메서드에서 ThreadFactory를 반환할 수 있습니다) :
Executors.newSingleThreadExecutor(new ThreadFactory() {
AtomicInteger threadCount = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "your-name-" + threadCount.getAndIncrement() + "-" + r.hashCode()); // could also use Integer.toHexString(r.hashCode()) for shorter
}
}));
그리고 그것을 변수로 "you-name-" 측면의 방법으로 만들 수 있다.또는 다른 답변처럼 컨스트럭터와 함께 별도의 클래스를 사용할 수도 있습니다.
언급URL : https://stackoverflow.com/questions/6113746/naming-threads-and-thread-pools-of-executorservice
'programing' 카테고리의 다른 글
사용 시기: Java 8+ 인터페이스 기본 방식과 추상 방식 비교 (0) | 2022.07.26 |
---|---|
posix_memalign/memalign의 기능 (0) | 2022.07.26 |
Vuex와 Redux의 불변성 접근방식의 차이점 (0) | 2022.07.26 |
여러 vuex createNamesched에 대한 베스트 프랙티스는 무엇입니까?도우미? (0) | 2022.07.26 |
활동 간에 데이터를 공유하는 가장 좋은 방법은 무엇입니까? (0) | 2022.07.26 |