Арендодатель, который серьезно набирал код, внезапно получил электронное письмо с предупреждением от системы обслуживания данных, в котором говорилось, что запланированная задача, которую арендодатель запустил рано утром, не удалась, поэтому сегодня арендодатель начал процесс поиска и заполнения ям.
Запланированные задачи, выбор между Timer и ScheduledExecutorService
В этом вопросе некоторые друзья обязательно скажут, почему Кварц не используется, потому что храм хозяина маленький, а задач на время всего несколько, Кварц слишком тяжелый.
Проблемы с таймером
Основная проблема с Timer заключается в том, что если TimerTask выдает непроверенное исключение, Timer будет вести себя непредсказуемо. Поток Timer не перехватывает исключения, поэтому непроверенное исключение, созданное TimerTask, завершит поток таймера, и в этом случае Timer не возобновит выполнение потока; он ошибочно полагает, что весь Timer был отменен. В этот момент TimerTask, который был запланирован, но еще не выполнен, больше никогда не будет выполняться, и новые задачи не могут быть запланированы.
Использование ScheduledExecutorService
ScheduledExecutorService — это API, предоставляемый в пакете concurrent после JDK 1.5. ScheduledExecutorService правильно обрабатывает эту нештатную задачу, поэтому в JDK1.5 или более поздней версии JDK домовладелец не рекомендует использовать Timer. В другой статье о владельце ScheduledExecutorService также упоминается, заинтересованные друзья, пожалуйста, переместитеРеализация Java завершает выполнение запланированных задач в пуле потоков
возникающие проблемы
Разница между связкой Timer и ScheduledExecutorService упоминалась выше, что немного не по теме.Теперь суть дела.Ранним утром запланированное задание арендодателя не было успешно выполнено, потому что он использовал ScheduledExecutorService вместо Timer.Конечно, если используется проблема, вызванная таймером, арендодателю не нужно говорить. Начнем наш поисковый процесс
Проверить журнал
Получите журнал jstack службы с помощью инструмента jstack, предоставляемого JDK, следующим образом:
2018-07-18 15:39:09
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):
"Attach Listener" daemon prio=10 tid=0x00007f5bd0007800 nid=0x4e78 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"DestroyJavaVM" prio=10 tid=0x00007f5bec008800 nid=0x1dd5 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-4" prio=10 tid=0x00007f5bec4be000 nid=0x1df8 runnable [0x00007f5be88b2000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainDatagramSocketImpl.receive0(Native Method)
- locked <0x00000000e7e450b8> (a java.net.PlainDatagramSocketImpl)
at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:146)
- locked <0x00000000e7e450b8> (a java.net.PlainDatagramSocketImpl)
at java.net.DatagramSocket.receive(DatagramSocket.java:816)
- locked <0x00000000e7e450e8> (a java.net.DatagramPacket)
- locked <0x00000000e7e45110> (a java.net.DatagramSocket)
at com.yg84.chelaile.middleware.common.remotedata.protocol.udp.UDPReceiver$1.run(UDPReceiver.java:55)
at java.lang.Thread.run(Thread.java:745)
"pool-5-thread-1" prio=10 tid=0x00007f5bec4ba800 nid=0x1df6 waiting on condition [0x00007f5be89b3000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000e7f1e510> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1090)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
"kafka-producer-network-thread | producer-1" daemon prio=10 tid=0x00007f5bec497000 nid=0x1df2 runnable [0x00007f5be8ffe000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
- locked <0x00000000e7e45778> (a sun.nio.ch.Util$2)
- locked <0x00000000e7e45788> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000e7e45730> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
at org.apache.kafka.common.network.Selector.select(Selector.java:454)
at org.apache.kafka.common.network.Selector.poll(Selector.java:277)
at org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:260)
at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:229)
at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:134)
at java.lang.Thread.run(Thread.java:745)
"AsyncLoggerConfig-1" daemon prio=10 tid=0x00007f5bec32a800 nid=0x1dee waiting on condition [0x00007f5bf04c2000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000e7638090> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
at com.lmax.disruptor.BlockingWaitStrategy.waitFor(BlockingWaitStrategy.java:45)
at com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:55)
at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:123)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
"Service Thread" daemon prio=10 tid=0x00007f5bec0b3800 nid=0x1ddc runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=10 tid=0x00007f5bec0b1000 nid=0x1ddb waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=10 tid=0x00007f5bec0ae800 nid=0x1dda waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x00007f5bec0ac800 nid=0x1dd9 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=10 tid=0x00007f5bec08c000 nid=0x1dd8 in Object.wait() [0x00007f5bf163a000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000e74a07a0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x00000000e74a07a0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" daemon prio=10 tid=0x00007f5bec08a000 nid=0x1dd7 in Object.wait() [0x00007f5bf173b000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000e74a0848> (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 <0x00000000e74a0848> (a java.lang.ref.Reference$Lock)
"VM Thread" prio=10 tid=0x00007f5bec085800 nid=0x1dd6 runnable
"VM Periodic Task Thread" prio=10 tid=0x00007f5bec0b7000 nid=0x1ddd waiting on condition
JNI global references: 165
По логу jstack тупиковой ситуации не обнаружено, и ScheduledThreadPoolExecutor, открытый арендодателем, тоже работал нормально, проблем не обнаружено.
"pool-5-thread-1" prio=10 tid=0x00007f5bec4ba800 nid=0x1df6 waiting on condition [0x00007f5be89b3000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000e7f1e510> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1090)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Возьмите исходный код
Поскольку проблема заключается в том, что запланированная задача не выполняется, арендодатель намеревается взглянуть на код scheduleAtFixedRate в ScheduledExecutorService.
/**
* Creates and executes a periodic action that becomes enabled first
* after the given initial delay, and subsequently with the given
* period; that is executions will commence after
* {@code initialDelay} then {@code initialDelay+period}, then
* {@code initialDelay + 2 * period}, and so on.
* If any execution of the task
* encounters an exception, subsequent executions are suppressed.
* Otherwise, the task will only terminate via cancellation or
* termination of the executor. If any execution of this task
* takes longer than its period, then subsequent executions
* may start late, but will not concurrently execute.
*
* @param command the task to execute
* @param initialDelay the time to delay first execution
* @param period the period between successive executions
* @param unit the time unit of the initialDelay and period parameters
* @return a ScheduledFuture representing pending completion of
* the task, and whose {@code get()} method will throw an
* exception upon cancellation
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if command is null
* @throws IllegalArgumentException if period less than or equal to zero
*/
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
Конечно же, из следующего абзаца в документе этого метода вы, вероятно, знаете, что когда задача сталкивается с исключением, задача больше не будет выполняться. Естественно другие задачи не затрагиваются.
If any execution of the task encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via cancellation or termination of the executor. If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
Обзор
В соответствии с приведенным выше процессом анализа арендодателя мы можем знать, что причина проблемы заключается в том, что в коде выдается непроверенное исключение.Ниже приведен тестовый код арендодателя.Код очень прост в использовании ScheduledExecutorService для запуска две задачи по времени, одна из которых выдает нулевой указатель. Потоки исключений не перехватываются.
public class TestCase {
public static void main (String[] args) {
ScheduledExecutorService service = Executors
.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new TestJob(), 0, 1000, TimeUnit.MILLISECONDS);
service.scheduleAtFixedRate(new TestJob2(), 0, 1000, TimeUnit.MILLISECONDS);
}
static class TestJob implements Runnable {
int count = 0;
public TestJob() {
}
@Override
public void run() {
// try {
count++;
System.out.println("TestJob count : " + count);
if (count == 5) {
throw new NullPointerException();
}
// } catch (Exception e) {
// e.printStackTrace();
// }
}
}
static class TestJob2 implements Runnable {
int count = 0;
public TestJob2() {
}
@Override
public void run() {
count++;
System.out.println("TestJob2 count : " + count);
}
}
}
Результат выполнения кода: после того, как TestJob сгенерирует исключение, оно больше не будет выполняться, и TestJob2 может продолжать выполняться без каких-либо последствий.
задача решена
Основная причина проблемы найдена, а решение относительно простое. Конкретный код выглядит следующим образом.
static class TestJob implements Runnable {
int count = 0;
public TestJob() {
}
@Override
public void run() {
try {
count++;
System.out.println("TestJob count : " + count);
if (count == 5) {
throw new NullPointerException();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
резюме
В целом, эта проблема относительно проста и относительно скрыта. Конечно, это во многом связано с вашими обычными стандартами кодирования.
Добавить Автора
Оригинальная ссылка:Уууу. Пересаживайтесь на студию. Можете/статья/201…
Заявление об авторских правах: Неспециальное заявление является оригинальной работой данного сайта.При перепечатке указывайте автора и оригинальную ссылку.