Loading

Java的多线程

 

    Java使用Thread代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用就是执行一段程序流(完成一定的任务)。

Java使用线程执行体来代表这段程序流。

 1. 继承Thread类创建线程类

package org.apache;

public class ThreadDemo1 extends Thread {
	private int i;
	/*
	 * 重写run方法,也就是线程执行体
	 * 当线程类继承Thread类时,直接使用this即可取得当前线程
	 * 直接调用getName()方法即可返回当前线程的名字
	 */
	public void run(){
		for ( ; i<100;i++){
			System.out.println(getName() + " " + i);
		}
	}
	
	public static void main(String[] args) 
	{
		for (int i=0;i<100;i++){
			System.out.println(Thread.currentThread().getName() 
					+ " "+i);
			if(i==20){
				//创建并启动第一个线程
				new ThreadDemo1().start();
				//创建并启动第二个线程
				new ThreadDemo1().start();
			}
		}
	}
}

  执行结果:

注意:实际上该程序有三个线程,main()方法是主线程,显示的创建了两个子线程。

   Thread-0和Thread-1 i的值是不连续的,所以Thread-0和Thread-1不能共享Thread类的实例变量。

2. 实现Runnable接口创建线程类

package org.apache;

public class ThreadDemo2 implements Runnable {
	private int i;
	//当实现Runnable接口时必须用Thread.currentThread().getName()获取当前线程
	public void run() {
		for ( ; i<100;i++){
			System.out.println(Thread.currentThread().getName() + " " + i);
		}
	}

	public static void main(String[] args) {
		for (int i=0;i<100;i++){
			System.out.println(Thread.currentThread().getName() + " "+i);
			if (i==20){
				ThreadDemo2 td = new ThreadDemo2();
				//通过new Thread(target,name)方法创建线程
				new Thread(td,"线程1").start();
				new Thread(td,"线程2").start();
			}
		}

	}
}

  结果:

i的值是连续的,共享同一个线程类的实例变量(其实是线程的target类)

3.使用Callable和Future创建线程

FutureTask同时实现

Future接口--->接收call()方法的返回值

和Runnable接口--->可以作为Thread的target

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/*
 * 创建并启动有返回值的线程步骤:
 * 1. 创建Callable接口的实现类,并实现call()方法,作为线程执行体
 * 2. 使用FutureTask类包装Callable对象,该FutureTask对象封装了Callable对象的call()方法
 * 3. 使用FutureTask对象作为Thread对象的target创建并启动新线程
 * 4. 调用FutureTask对象的get()方法获得子线程的执行结束的返回值
 */
public class ThreadDemo3 implements Callable{
	private int i;
	
	public Object call() throws Exception {
		for ( ; i<100;i++){
			System.out.println(Thread.currentThread().getName() + " " + i);
		}
		return i;
	}

	public static void main(String[] args) {
		ThreadDemo3 td = new ThreadDemo3();
		//通过new Thread(target,name)方法创建线程
		FutureTask<Integer> task = new  FutureTask<Integer>(td);
		for (int i=0;i<100;i++){
			System.out.println(Thread.currentThread().getName() + " "+i);
			if (i==20){
				new Thread(task,"有返回值的线程").start();
			}
		}
		try {
              //获取线程返回值 System.out.println(task.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }

  结果:

 

4. 控制线程

4.1 join线程

当程序程序执行流中调用其它线程的join()方法时,调用线程将会被阻塞。直到被join的线程执行完成。

package org.apache;

public class ThreadDemo1 extends Thread {
	public ThreadDemo1 (String name){
		super(name);
	}
	private int i;
	/*
	 * 重写run方法,也就是线程执行体
	 * 当线程类继承Thread类时,直接使用this即可取得当前线程
	 * 直接调用getName()方法即可返回当前线程的名字
	 */
	public void run(){
		for ( ; i<100;i++){
			System.out.println(getName() + " " + i);
		}
	}
	
	public static void main(String[] args) throws InterruptedException 
	{
		new ThreadDemo1("新线程").start();
		for (int i=0;i<100;i++){
			Thread task = new ThreadDemo1("被join的线程");
			System.out.println(Thread.currentThread().getName() 
					+ " "+i);
			if(i==20){
				//创建并启动第一个线程
				task.start();
				//main调用了join()方法,必须等task执行结束后才会向下执行
				task.join();
			}
		}
	}
}

  

  执行结果:

 分析可知main方法(主线程)被阻塞,只有新线程和join线程并发执行。

 

4.2 守护线程

有一种线程是为其它线程提供服务的(典型的有GC),被称为后台线程或者守护线程。

package org.apache;

public class ThreadDemo4 extends Thread{
	private int i;
	public void run(){
		for (;i<1000;i++){
			System.out.println(getName() + " "+i);
		}
	}

	public static void main(String[] args) {
		ThreadDemo4 task = new ThreadDemo4();
		//设置为守护进程
		task.setDaemon(true);
		task.start();
		for( int i=0;i<10;i++){
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
		//程序执行到此处就main进程就结束了,JVM将会主动退出,守护线程也将被结束,无法执行到=999
	}
}

 执行结果: 

 

4.3 线程睡眠:sleep
package org.apache;

import java.util.Date;

public class ThreadDemo5 {
      //正在执行的线程将会暂停一段时间,进入阻塞状态
	public static void main(String[] args) throws InterruptedException {
		for (int i=0;i<10;i++){
			System.out.println("当前时间: "+new Date());
			Thread.sleep(1000);
		}
	}
}

  结果:

 

posted @ 2017-05-07 17:16  头痛不头痛  阅读(289)  评论(0编辑  收藏  举报