Другим сценарием является то, что вы нанесли нулевой объект в тип значения . Например, код ниже:
object o = null;
DateTime d = (DateTime)o;
Он выкинет NullReferenceException
в роли. В приведенном выше примере это кажется совершенно очевидным, но это может произойти в более «поздних связующих» сложных сценариях, где нулевой объект был возвращен из некоторого кода, которого вы не являетесь, и приведение, например, генерируется некоторой автоматической системой.
Одним из примеров этого является этот простой фрагмент привязки ASP.NET с элементом управления календарем:
" />
Здесь SelectedDate
на самом деле является свойством - типа DateTime
- типа Calendar
Web Control, и привязка может отлично вернуть что-то null. Неявный генератор ASP.NET создаст кусок кода, который будет эквивалентен приведенному выше методу. И это поднимет NullReferenceException
, что довольно сложно определить, потому что он лежит в сгенерированном ASP.NET коде, который компилирует отлично ...
Дизайн этого зависит от того, что вы хотите делать за 15 секунд. Два наиболее правдоподобных случая: «сделайте это каждый X за 15 секунд» или «дождитесь появления X или 15 секунд, что произойдет раньше», что приведет к очень разному коду.
Это не повторение, но если вы ничего не хотите делать за 15 секунд, это намного эффективнее (он тратит меньше процессор на то, чтобы ничего не делать) .
Если вы действительно хотите зацикливаться на 15 секунд, тогда ваше решение будет прекрасным, если ваш код не займет слишком много времени. Что-то вроде:
long t= System.currentTimeMillis();
long end = t+15000;
while(System.currentTimeMillis() < end) {
// do something
// pause to avoid churning
Thread.sleep( xxx );
}
Если вы хотите, чтобы ваш код был прерван ровно 15 секунд, что бы он ни делал, вам понадобится многопоточный решение. Посмотрите на java.util.concurrent для множества полезных объектов. Большинство методов, которые блокируют (например, wait ()), имеют аргумент тайм-аута. Семафор может выполнять именно то, что вам нужно.
Никогда не проверяйте текущее время в плотной петле.
В противном случае кто-то с ноутбуком может получить, чтобы его / ее колпак загорелся перегретым процессором. Я слышал рассказы об этом на самом деле.
Как уже упоминалось в других плакатах, если вы хотите, чтобы поток некоторое время приостанавливался, используйте Thread.sleep()
.
Если вы хотите, чтобы нить что-то делал, но хотите остановить его после while, используйте что-то вроде:
class Foo implements Runnable {
private volatile boolean killed = false;
public void run() {
while (!killed) {
try { doOnce(); } catch (InterruptedException ex) { killed = true; }
}
}
public void kill() { killed = true; }
private void doOnce() throws InterruptedException { /* .. */ }
}
и из основного потока, do:
Foo foo = new Foo();
Thread thread = new Thread(foo);
thread.start();
/* when you want to stop it */
foo.kill();
thread.interrupt();
Я предлагаю вам сделать это с помощью класса таймера, избегая Thread.sleep (xxx); метод.
, например:
import java.util.Timer;
import java.util.TimerTask;
public class TimerExample {
private int globalTimer = 0;
private int limitTimer = 15;
public static void main(String[] args) {
new TimerExample();
}
public TimerExample() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
globalTimer++;
// DO YOUR CODE HERE
System.out.println("running");
if (globalTimer == limitTimer) {
timer.cancel();
}
}
}, 0, 1000);
}
}
попробуйте следующее:
public class SleepMessages {
public static void main(String args[]) throws InterruptedException {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
for (int i = 0; i < importantInfo.length; i++) {
//Pause for 15 seconds
Thread.sleep(15000);
//Print a message
System.out.println(importantInfo[i]);
}
}
}
подробнее: здесь
Вот мое предложение, и оно работает хорошо для меня :)
StoppingTime = 15 ;
int loop = 1;
long StartTime = System.currentTimeMillis() / 1000 ;
for (int i=0; i<loop; ++i) {
// your code here
loop++;
if (((System.currentTimeMillis()/1000) - StartTime) > StoppingTime)
loop=0;
}
Решение, подобное @Tom Hawtin без размера сурового цикла.
final long end = System.nanoTime() + 15 * 1000 * 1000 * 1000L;
int loop = 1;
do {
for (int i=0; i<loop; ++i) {
...
}
loop++;
} while (System.nanoTime() < end);
В этом случае размер внутренней петли начнет уменьшаться, но увеличится в размере, если цикл будет особенно быстрым. Если он достаточно медленный, он может выполнять только один раз.
Ваш общий подход кажется прекрасным, хотя вы можете посмотреть, больше ли текущее время, чем точка, которую вы хотите остановить, иначе вы могли бы работать в течение длительного времени.
Альтернативой является запустите таймер / поток, который устанавливает флаг через 15 секунд. Этот флаг должен быть отмечен как изменчивый, иначе ваш цикл может не увидеть изменения в значении.
Выбор, если вы заботитесь об эффективности, является более дорогостоящим, получая системное время один раз за цикл или доступ к изменчивой переменной? Я не знаю, какой из них более эффективен - вы можете сравнить его, если это действительно важно.
Для простого, поддерживаемого кода я бы выбрал подход проверки таймера:
long endTime = System.currentTimeMillis() + 15000
while (System.currentTimeMillis() < endTime) {
//loop
}
Для подхода java.util.concurrent см. главу 6 Java Concurrency in Practice (раздел 6.3.7. Установка временных ограничений для задач, стр. 131).
Пример кода: Получение рекламы с использованием бюджета времени.
Предполагая, что вы хотите, чтобы цикл делал что-то разумное, вы можете быстрее найти флажок волатильности. Еще один поток подождите 15 секунд (или используйте таймер), а затем установите его.
В качестве альтернативы, если вы знаете, сколько времени займет тело цикла, запустите его несколько сотен раз, скажем, и выполните
final long start = System.nanoTime();
do {
for (int i=0; i<200, ++i) {
...
}
} while (System.nanoTime()-start < 15L*1000L*1000L*1000L);
System.nanoTime
должно не путаться изменениями системных часов. Важно использовать длинные литералы.
Вы можете использовать AOP и @Timeable
аннотацию из jcabi-аспектов (я разработчик):
@Timeable(limit = 1, unit = TimeUnit.SECONDS)
String load(String resource) {
// do this check regularly:
if (Thread.currentThread.isInterrupted()) {
throw new IllegalStateException("time out");
}
// execution as normal
}
Когда ограничение времени достигнет вашего потока, который установит флаг interrupted()
, установленный на true
, и ваше задание правильно справится с этой ситуацией и прекратит выполнение.
Возможно, вам будет интересно планировать TimerTask, который останавливает другой поток или изменяет состояние вашего цикла.