[Java笔记] 多线程(一)——线程的创建和启动


这是我在学习疯狂Java讲义期间的笔记,如有错误请指出。

一、问题提出:
(一)、单线程与多线程的区别?
  1. 单线程只有一条顺序执行流;多线程可以有多条顺序执行流,并且多天顺序执行流互不干扰。
  2. 单线程需要完成当前事件后才能执行下一事件;多线程可以同时执行多件事情。
(二)、进程与线程的区别?

进程:

  1. 进程= 程序代码 + 数据 + PCB;
  2. 并发型: 多个进程可以在单处理器并发执行;

线程:

  1. 同一个进程可以并发处理多个任务;
  2. 线程是进程的执行单位;
  3. 一个线程可以创建和撤销另一个线程;
  4. 共享内存、文件句柄和其它每个进程应有状态,线程可以拥有自己的堆栈、程序计数器和局部变量。
二、线程的创建和启动
(一)、继承Thread类创建线程类
public class FirstThread extends Thread
{
   private int i ;
   // 重写run方法,run方法的方法体就是线程执行体
   public void run()
   {
   	for ( ; i < 10 ; i++ )
   	{
   		// 当线程类继承Thread类时,直接使用this即可获取当前线程
   		// Thread对象的getName()返回当前该线程的名字
   		// 因此可以直接调用getName()方法返回当前线程的名
   		System.out.println(getName() +  " " + i);
   	}
   }
   public static void main(String[] args)
   {
   	for (int i = 0; i < 10;  i++)
   	{
   		// 调用Thread的currentThread方法获取当前线程
   		System.out.println(Thread.currentThread().getName()
   			+  " " + i);
   		if (i == 5)
   		{
   			// 创建、并启动第一条线程
   			new FirstThread().start();
   			// 创建、并启动第二条线程
   			new FirstThread().start();
   		}
   	}
   }
}


执行结果

main 0
main 1
main 2
main 3
main 4
main 5
Thread-0 0
Thread-0 1
main 6
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-1 5
Thread-1 6
Thread-1 7
Thread-1 8
Thread-1 9
main 7
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
main 8
main 9

每次执行结果不同;输出 i 的值不连续,因为每次创建线程对象时都需要创建一个FirstThread对象,所以Thread-0和Thread-1不能共享该实例变量i。使用继承Thread类的方法来创建线程类时,多个线程之间无法共享线程类的实例变量

(二)、继承Runnable接口创建线程类
public class SecondThread implements Runnable
{
  private int i ;
  // run方法同样是线程执行体
  public void run()
  {
  	for ( ; i < 10 ; i++ )
  	{
  		// 当线程类实现Runnable接口时,
  		// 如果想获取当前线程,只能用Thread.currentThread()方法。
  		System.out.println(Thread.currentThread().getName()
  			+ "  " + i);
  	}
  }

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


执行结果

main  0
main  1
main  2
main  3
main  4
main  5
Thread-0  0
Thread-0  1
Thread-0  2
新线程2  2
Thread-0  3
新线程2  4
Thread-0  5
新线程2  6
Thread-0  7
新线程2  8
Thread-0  9
main  6
main  7
main  8
main  9
(三)、使用Callable 和Future创建线程

        Thread类的作用是把run()方法包装程线程执行体,但Java目前不能直接把任意方法都包装成线程执行体。
        Callable提供call()可作为线程执行体,call()功能比run()强大。Callable对象不能直接作为Thread的target,并且call()拥有返回值——call()方法不能直接调用,他作为线程执行体被调用。Future接口代表Callabel接口里call()方法的返回值,并为Future 接口提供FutureTassk实现类,该实现类实现Future接口,并实现Runnable接口——可作为Thread类的target。

public class ThirdThread
{
	public static void main(String[] args)
	{
		// 创建Callable对象
		ThirdThread rt = new ThirdThread();
		// 先使用Lambda表达式创建Callable<Integer>对象
		// 使用FutureTask来包装Callable对象
		FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)() -> {
			int i = 0;
			for ( ; i < 10 ; i++ )
			{
				System.out.println(Thread.currentThread().getName()
					+ " 的循环变量i的值:" + i);
			}
			// call()方法可以有返回值
			return i;
		});
		for (int i = 0 ; i < 10 ; i++)
		{
			System.out.println(Thread.currentThread().getName()
				+ " 的循环变量i的值:" + i);
			if (i == 5)
			{
				// 实质还是以Callable对象来创建、并启动线程
				new Thread(task , "有返回值的线程").start();
			}
		}
		try
		{
			// 获取线程返回值
			System.out.println("子线程的返回值:" + task.get());
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
	}
}

执行结果

main 的循环变量i的值:0
main 的循环变量i的值:1
main 的循环变量i的值:2
main 的循环变量i的值:3
main 的循环变量i的值:4
main 的循环变量i的值:5
main 的循环变量i的值:6
main 的循环变量i的值:7
main 的循环变量i的值:8
main 的循环变量i的值:9
有返回值的线程 的循环变量i的值:0
有返回值的线程 的循环变量i的值:1
有返回值的线程 的循环变量i的值:2
有返回值的线程 的循环变量i的值:3
有返回值的线程 的循环变量i的值:4
有返回值的线程 的循环变量i的值:5
有返回值的线程 的循环变量i的值:6
有返回值的线程 的循环变量i的值:7
有返回值的线程 的循环变量i的值:8
有返回值的线程 的循环变量i的值:9
子线程的返回值:10
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值