Java多线程编程入门(一)

进程与线程:

多任务操作系统Windows中的进程展示

通过上图我们可以具体地从直观上理解进程到底是什么,而不是像百度百科上的解释那样让人理解起来很吃力。

进程:进程是受操作系统管理的基本运行单元,可以将在内存中运行的exe文件理解为进程;
线程:线程是在进程中独立运行的子任务;

使用多线程和不使用多线程的区别:
	使用多线程技术,可以使CPU在多个任务(线程)之间不停地切换,由于切换的速度非常快,给用户的感觉就像是在同一时间,执行多个任务;
	不使用多线程的程序,排队执行不同的任务,也就是同步执行;使用多项城的程序,是由CPU调度执行不同的任务,也就是异步执行;使用 
多线程,可以在相同的时间内执行多个任务,大大提高CPU的利用率;

一旦使用多线程,一定要注意:						
	多线程是异步的,不能把程序中的代码顺序当做线程执行的顺序,线程调用的时机是随机的!

从头开始理解Java中的线程
看过Java线程相关书籍的Java开发人员都知道,如何实现自定义线程,比如继承Thread类重写run方法、实现Runnable接口重写run方法以及实现Callable接口重写call方法并对Callable实现类的实例进行包装等,但是,为什么通过这些方式就可以实现自定义线程呢?下面通过分析JDK中线程相关的源码来梳理线程的脉络;

首先,根据上面提到的几种实现自定义线程方式可以看出自定义线程必须重写run方法,那么看一下,JDK中run方法的出处在哪?通过源码我们可以找到,run方法的出处在于Runnable接口,如下所示:

public interface Runnable {
        /**
         * Runnable接口可以用来被任何一个类实现,来保证该实现类的实例可以被一个线程执行
         * 线程所执行的任务就是实例中的run方法内的具体实现
         * @see     java.lang.Thread#run()
         */
        public abstract void run();
    }

从源码可以得知,Runnable接口给出了线程应该实现的线程体(run()),该方法是一个线程的唯一任务;采用接口的形式给出线程体的规范,而不是通过类的形式,是因为接口更具扩展性!

创建自定义线程类
首先,需要了解Java中JDK开发包中的Thread线程类,这样会有助于学会如何创建自定义线程类;
Thread类的结构:

public class Thread implements Runnable

那么,在实际开发中,我们并不会直接使用Thread类一般不会创建自定义线程类的两种方式:

①继承Thread类,格式如下:

	public MyThread extends Thread{
		@Override
		public void run(){
			//此线程类的线程对象需要完成的任务
		}
	}
②实现Runnable接口
第一步:设计一个实现了Runnable接口的类
public class MyRunnable implements Runnable
{
	@Override
	public void run()
	{
		//本线程类的线程对象需要完成的任务
		... ...
	}
}
第二步:将该类的实例对象传入Thread类中的含参构造器中,进行线程的实例化;
public static void main(String[] args)
{
	Runnable runnable = new MyRunnable();
	Thread thread = new Thread(runnable);
	thread.start();
	System.out.println("运行结束!");
} 

两种方式的比较:
	第一种方式使用继承Thread类,所以在遇到某个类已经继承一个类的情况下,就不能使用这种方式将该类设计为线程类,因为Java是不支持多继承的;
	第二种方式使用实现接口的方式,就避免了第一种方式的局限性,从而可以边实现接口边继承其他的类来设计自定义线程类;


下面通过一个简单的Java项目,从直观上感受一下,使用多线程的程序,其代码的顺序,不代表实际的执行顺序;
package thread.mythread;

public class MyThread extends Thread{
	@Override
	public void run() {
	super.run();
	System.out.println("自定义线程结束!");
	}	
	public static void main(String[] args) {
		MyThread thread = new MyThread();//①
		thread.start();//②
		System.out.println("运行结束!");//③
	}
}

程序运行结果如下图所示:
这里写图片描述

	这里我们需要注意,自定义线程类中的run方法是重写了父类Thread中的方法,同时自定义线程类还继承了Thread类中的start方法, 
当线程对象调用start方法时通知“线程规划器”此线程已经准备就绪,等待CPU调用该线程对象的run方法,这个过程可以理解为start方法的调用
通知了系统,使其安排一个时间来调用该线程的run方法,也就是使该线程对象得到运行,启动线程,从而产生异步执行的效果。
	从执行结果可以明显地看到第②句执行完后,执行第③句,第③句执行输出后,接着又执行了子线程中的run方法,输出了自定义线程结束! 
说明在第②句执行完后,线程已经启动,但并没有立即执行线程中的run方法,而是在执行完第③步之后才执行,说明,使用了多线程的程序,执行顺序 
并不一定就是代码的顺序!
	从这里我们可以知道,线程是一个子任务,CPU以不确定的方式,或者说是以随机的时间来调用线程中的run方法,所以才会出现上面的
运行结果。
	这里需要注意:如果通过线程对象thread调用run方法,那么就不是异步执行,而是执行main方法的线程在执行run方法,这时采用
同步执行的方式,执行代码,当执行完run方法后,再执行接下来的语句!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值