понедельник, 23 мая 2011 г.

Многопоточность в java. Пример

Удобство
Да, многопоточность в яве действительно сделана хорошо. Инструменты удобны и если хочется получить какой-то высокоуровневый инструмент для многопоточной программы, то он существует (а если нет, то один из существующих наверняка лучше того, который хотелось увидеть).
Простой пример:
private static String[] sites = 
    {"www.google.com", "www.ya.ru", "www.yahoo.com"};
//создание пула потоков    
ExecutorService service = Executors.newCachedThreadPool();
List<Future<String>> futures = 
    new ArrayList<Future<String>>();
for (int i = 0; i < sites.length; ++i) {
    //запуск нового потока с параметром из массива
    Future<String> future = 
        service.submit(new ThreadWorker(sites[i]));
    futures.add(future);
    }
//на этом этапе все потоки запущены
System.out.println("threads started");
for (Future<String> future : futures) {
    //забираем результат выполнения потока
    //если поток ещё не завершился, то происходит ожидание
    System.out.println("get result from Future: " + future.get());
}
//сообщаем пулу о том, что закончили пользоваться потоками
service.shutdown();
Подробнее?

пятница, 20 мая 2011 г.

Форматированный вывод вещественных чисел

Постоянно если сталкиваюсь, то пытаюсь вспомнить, что ж там надо писать в строке формата String.format, чтобы вывести в том виде, в котором нужно. И постоянно приходится или угадывать, или гуглить. Даже не знаю, что быстрее. Поэтому стоит записать, как же получить нормальное строковое представление для float/double немного альтернативным способом:
NumberFormat format = new DecimalFormat("#.##", 
    new DecimalFormatSymbols(Locale.US));
String result = format.format(doubleParam);

Второй параметр у конструктора можно не указывать. По умолчанию используется локаль системы. Мне было неудобно, т.к. нужна была точка в качестве разделителя целой и дробной части, а русская локаль ставит запятую.
Как это сработает?
1.4 "1.4"
1.333"1.33"
1.89999"1.9"
16.23"16.23"

Тесты

Нет, заметка не о jUnit, хоть я и люблю их.
Хотел поделиться новостью: http://www.quizful.net снова работает.
Кстати, на прошлую заметку меня натолкнул тест именно на этом ресурсе

Численные методы на службе прикладного программиста

Точность чисел
На определённые исследования по этой теме меня сподвиг вопрос теста:
long l1 = Long.MAX_VALUE;
long l2 = Long.MAX_VALUE-1;
double d1 = Long.MAX_VALUE;
System.out.println("l1 == d1: " + (l1 == d1));
System.out.println("l2 == d1: " + (l2 == d1));
Чтобы никто не мучился, сразу скажу, вывод даст:
l1 == d1: true
l2 == d1: true

Почему?

вторник, 19 апреля 2011 г.

Массив в коллекцию, пожалуйста. И чтобы покороче

Особенности Arrays.asList(T... elements)
Arrays.asList(T... elements) и Collection.toArray() являются стандартным (так говорят javadoc'и) мостом между библиотеками, работающими с массивами и коллекциями. Звучит красиво, что уж там.
Немногие дочитывают до того места, в котором говорится, что полученный List является fixed-size. А это означает, например, что оттуда нельзя удалить элемент. Этот баг можно быстро найти и понять, но тем не менее. В общем, я был неприятно удивлён. Что побудило Sun реализовать метод именно так я не смог понять (поэтому мне сложно решить, пометить запись меткой "фича" или "кривота"...выберу обе).
Как лечится?
Например, так:
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3));

понедельник, 11 апреля 2011 г.

Переименовать таблицу или колонку

Парочка мелких вещей в SQL, которые меня слегка удивили.
  • В БД при изменении имени таблиц все constraints автоматически подстраиваются под это изменение. То есть никаких ошибок не возникнет (входит в стандарт и работает на абсолютном большинстве БД).
    ALTER TABLE MyTable RENAME TO MY_TABLE;
    
  • Но Oracle пошёл и того дальше. Он умеет даже переименовывать колонки. При этом даже если это Primary Key. Даже если на колонку навешены другие индексы, даже если на неё ссылается Foreign Key из другой таблицы. К сожалению, эта фишка не из стандарта, поэтому в других БД может и не быть (в MySQL нет, например).
    ALTER TABLE MyTable RENAME COLUMN id TO identifier;
    

воскресенье, 3 апреля 2011 г.

Асимметрия

Вопрос:
Может ли функция Math.abs(int) вернуть отрицательное число?

Ответ:
Как же хочется написать "нет", улыбнуться и подумать, что я всех обманул таким вопросом. На самом деле может. Так уж повелось, что отрицательных чисел больше, чем положительных. Так уж повелось, что если byte, то диапазон -128..127, ну и так далее с увеличением количества байт на хранение. К чему это приводит?
int minValue = Integer.MIN_VALUE;
int abs = Math.abs(minValue);
System.out.println(abs);
Закрываем, трясём, смотрим (©):
> -2147483648