java多线程与单线程相比,最大的优点是在多任务的情况下多线程比单线耗时短,可以并发进行
有时候对于单核计算机,我们也觉得很多任务是并发进行的,主要是因为我们的单核cpu对时间进行分片,对
每个任务都分配了时间片。比如给qq分配3ms给腾讯视频分了3ms等等,虽然我们看任务是并行的,实则是
分时运行的。而多核cpu则可以真正并发,这就是多核cpu执行的优势。
下面有一个简单的程序是对java单线程多线程的比较
public class ConcurrencyTest {
private static final long count = 1000000001;
public static void main(String args[]) throws InterruptedException
{
concurrency();
seria();
}
//多线程情况下
private static void concurrency() throws InterruptedException
{ //获取当前系统时间
long start = System.currentTimeMillis();
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
long a = 0;
for(int i = 0;i < count;i++)
{
a+=5;
}
}
});
thread.start();
long b = 0;
for(int i = 0;i <count;i++)
{
b+=5;
}
thread.join();//简单理解为等待线程结束,如果线程没有结束的话时间统计不准确
long time = System.currentTimeMillis() - start;
System.out.println("concurrency: " +time +" b: "+ time);
}
//顺序执行的情况
private static void seria()
{
long start = System.currentTimeMillis();
long a = 0;
for(int i = 0;i < count;i++)
{
a+=5;
}
long b = 0;
for(int i = 0;i <count;i++)
{
b+=5;
}
long time = System.currentTimeMillis() - start;
System.out.println("concurrency: " +time +" b: "+ time);
}
}
package java_Join;
public class ConcurrencyTest {
private static final long count = 1000000001;
public static void main(String args[]) throws InterruptedException
{
concurrency();
seria();
}
//多线程情况下
private static void concurrency() throws InterruptedException
{ //获取当前系统时间
long start = System.currentTimeMillis();
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
long a = 0;
for(int i = 0;i < count;i++)
{
a+=5;
}
}
});
thread.start();
long b = 0;
for(int i = 0;i <count;i++)
{
b+=5;
}
thread.join();//简单理解为等待线程结束,如果线程没有结束的话时间统计不准确
long time = System.currentTimeMillis() - start;
System.out.println("concurrency: " +time +" b: "+ time);
}
//顺序执行的情况
private static void seria()
{
long start = System.currentTimeMillis();
long a = 0;
for(int i = 0;i < count;i++)
{
a+=5;
}
long b = 0;
for(int i = 0;i <count;i++)
{
b+=5;
}
long time = System.currentTimeMillis() - start;
System.out.println("concurrency: " +time +" b: "+ time);
}
}
其中执行的任务越大,效果越明显。
其中对join的理解其中有参照
个人简单理解是将该线程加入到主线程,主线程要等待其结束,如果该线程没有结束主线程不能结束
比如,你想喝茶,你要烧水,洗茶具,泡茶,喝茶。烧水与洗茶具没什么关联,你可以分开进行,但
是你喝茶的话必须得每件事都完成,所以烧水这种费时的动作就交由一个线程去做,等洗好茶具等烧
水线程完成,就可以泡茶喝茶了。
一、使用方式。
join是Thread类的一个方法,启动线程后直接调用例如
Thread t = new AThread(); t.start(); t.join();
二、为什么要用join()方法
在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
三、join方法的作用
join
public final void join() throws InterruptedException Waits for this thread to die.
Throws: InterruptedException - if any thread has interrupted the current thread.
The interrupted status of the current thread is cleared when this exception is thrown.
即join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。四、从源码看join()方法
join()的JDK源码
/**
* Waits for this thread to die.
* <p> An invocation of this method behaves in exactly the same
* way as the invocation
*
* <blockquote>
* {@linkplain #join(long) join}{@code (0)}
* </blockquote>
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public final void join() throws InterruptedException {
join(0);
}
/**
* Waits at most {@code millis} milliseconds for this thread to
* die. A timeout of {@code 0} means to wait forever.
*
* <p> This implementation uses a loop of {@code this.wait} calls
* conditioned on {@code this.isAlive}. As a thread terminates the
* {@code this.notifyAll} method is invoked. It is recommended that
* applications not use {@code wait}, {@code notify}, or
* {@code notifyAll} on {@code Thread} instances.
*
* @param millis
* the time to wait in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
五、用实例来理解
写一个简单的例子来看一下join()的用法:
主要包含三个类
1.TestDemo 类
1.AThread 类
2.BThread类
TestDemo 类是主类main线程,主类里面加入了AThread 类的线程,AThread 类又加入了BThread类
-
class AThread extends Thread { BThread bt; public AThread(BThread bt) { super("[AThread] Thread"); this.bt = bt; } public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName + " start."); try { // 这里加入了bt线程 bt.join(); System.out.println(threadName + " end."); } catch (Exception e) { System.out.println("Exception from " + threadName + ".run"); } } }
class BThread extends Thread { public BThread() { super("[BThread] Thread"); }; public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName + " start."); try { for (int i = 0; i < 5; i++) { System.out.println(threadName + " loop at " + i); Thread.sleep(1000); } System.out.println(threadName + " end."); } catch (Exception e) { System.out.println("Exception from " + threadName + ".run"); } } }
public class TestDemo { public static void main(String[] args) { String threadName = Thread.currentThread().getName(); System.out.println(threadName + " start."+"时间 :"+System.currentTimeMillis()); BThread bt = new BThread(); AThread at = new AThread(bt); try { bt.start(); Thread.sleep(2000); at.start(); at.join(); } catch (Exception e) { System.out.println("Exception from main"); } System.out.println(threadName + " end!"+"时间 :"+System.currentTimeMillis()); } }
最后结果为
可以看得到进程运行变化。
main start.时间 :1497456321225
//主线程起动,因为调用了at.join(),要等到at结束了,此线程才能向下执行
主线程睡眠2000ms
[BThread] Thread start.时间 :1497456321226[BThread] Thread loop at 0时间 :1497456321226
//睡眠1000ms
[BThread] Thread loop at 1时间 :1497456322230
//睡眠1000ms
[BThread] Thread loop at 2时间 :1497456323231
[AThread] Thread start.
//A程起动,因为调用了bt.join(),要等到bt结束了,此线程才能向下执行
[BThread] Thread loop at 3时间 :1497456324236
[BThread] Thread loop at 4时间 :1497456325241
[BThread] Thread end.时间 :1497456326245
[AThread] Thread end.
// 线程AThread在bt.join();阻塞处开始启动,向下继续执行的结果
main end!
//线程AThread结束,此线程在at.join();阻塞处开始启动,向下继续执行的结果。
修改主方法类:
public class TestDemo { public static void main(String[] args) { String threadName = Thread.currentThread().getName(); System.out.println(threadName + " start."+"时间 :"+System.currentTimeMillis()); BThread bt = new BThread(); AThread at = new AThread(bt); try { bt.start(); Thread.sleep(2000); at.start(); //at.join(); //在此处注释掉对join()的调用 } catch (Exception e) { System.out.println("Exception from main"); } System.out.println(threadName + " end!"+"时间 :"+System.currentTimeMillis()); } }
结果为 main start.时间 :1497457025126 // 主线程起动,因为Thread.sleep(2000),主线程没有马上结束; [BThread] Thread start.时间 :1497457025128 //线程BThread起动 [BThread] Thread loop at 0时间 :1497457025128 [BThread] Thread loop at 1时间 :1497457026128 main end!时间 :1497457027128 //2000ms后主线程结束,留下AThread,与BThread [AThread] Thread start. //2000ms线程at启动,因为调用了bt.join(),等到bt结束了,此线程才向下执行。 [BThread] Thread loop at 2时间 :1497457027128 [BThread] Thread loop at 3时间 :1497457028130 [BThread] Thread loop at 4时间 :1497457029131 [BThread] Thread end.时间 :1497457030137 //线程BThread结束了,线程AThread在bt.join();阻塞处开始启动,向下继续执行的结果 [AThread] Thread end.
参考文章:http://www.open-open.com/lib/view/open1371741636171.html