Вам действительно нужно сделать это из папки src
. Там вы вводите следующую командную строку:
[name of the package].[Class Name] [arguments]
Допустим, ваш класс называется CommandLine.class
, и код выглядит следующим образом:
package com.tutorialspoint.java;
/**
* Created by mda21185 on 15-6-2016.
*/
public class CommandLine {
public static void main(String args[]){
for(int i=0; i<args.length; i++){
System.out.println("args[" + i + "]: " + args[i]);
}
}
}
Затем вы должны cd
в папку src и команда, которую вам нужно запустить, будет выглядеть так:
java com.tutorialspoint.java.CommandLine this is a command line 200 -100
И вывод в командной строке будет:
args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100
Секундомер не является потокобезопасным, особенно для 32-разрядных программ.
Он использует вызов Windows API QueryPerformanceCounter()
для обновления частного длинного поля. В 32-битных системах вы можете получить «рваное чтение», когда один поток читает длинное значение, а другой поток обновляет его.
Чтобы исправить это, вам нужно будет заблокировать доступ к Секундомер.
Также обратите внимание, что в некоторых старых системах были ошибки, в которых непоследовательные значения могли быть возвращены из разных потоков, вызывающих QueryPerformanceCounter()
. Из документации:
На многопроцессорном компьютере не должно иметь значения, какой процессор вызывается. Тем не менее, вы можете получить разные результаты на разных процессорах из-за ошибок в базовой системе ввода / вывода (BIOS) или слоя абстракции аппаратного обеспечения (HAL). Чтобы указать сродство процессора к потоку, используйте функцию SetThreadAffinityMask.
blockquote>Я никогда не сталкивался с этой ошибкой сам, и я не думаю, что это очень распространено.
Какие результаты вы получаете со следующей тестовой программой? Время должно быть в основном возрастающим по стоимости, но вы можете получить один или два порядка, просто потому, что их потоки будут перенесены после того, как они прочитают значение и до того, как они добавят его в очередь.
namespace Demo { class Program { Stopwatch sw = Stopwatch.StartNew(); object locker = new object(); ConcurrentQueue<long> queue = new ConcurrentQueue<long>(); Barrier barrier = new Barrier(9); void run() { Console.WriteLine("Starting"); for (int i = 0; i < 8; ++i) Task.Run(()=>test()); barrier.SignalAndWait(); // Make sure all threads start "simultaneously" Thread.Sleep(2000); // Plenty of time for all the threads to finish. Console.WriteLine("Stopped"); foreach (var elapsed in queue) Console.WriteLine(elapsed); Console.ReadLine(); } void test() { barrier.SignalAndWait(); // Make sure all threads start "simultaneously". for (int i = 0; i < 10; ++i) queue.Enqueue(elapsed()); } long elapsed() { lock (locker) { return sw.ElapsedTicks; } } static void Main() { new Program().run(); } } }
Сказав все это, наиболее очевидным ответом является то, что на самом деле вы не используете один секундомер между потоками, но вместо этого вы случайно запустили новый для каждого потока ...