线程基础图
上篇博客我们从操作系统宏观的说了说线程和线程的Boss进程是什么,以及他们之间的关系,那么这篇博客,我们开始了解一下线程基础的知识。
下图是关于使用线程的最最基本的入门功能:
线程创建
在java中如何创建一个线程?
简单的说有两种方法:使用java.lang.Thread类或者java.lang.Runnable接口编写代码来定义、实例化和启动新线程。不论是使用继承Thread方法,还是实现Runnable接口,都需要复写 run()方法。线程启动后,run()是线程执行的核心。
我们使用Thread 来创建一个线程:
/**
* 测试扩展Thread类实现的多线程程序
*
* @author leizhimin 2008-9-13 18:22:13
*/
publicclass TestThreadextends Thread{
public TestThread(String name) {
super(name);
}
publicvoid run() {
for(int i = 0;i<5;i++){
for(long k= 0; k <100000000;k++);
System.out.println(this.getName()+" :"+i);
}
}
}
然后再使用实现Runnable接口来创建一个线程:
/**
* 实现Runnable接口的类
*
* @author leizhimin 2008-9-13 18:12:10
*/
publicclass DoSomethingimplements Runnable {
private String name;
public DoSomething(String name) {
this.name = name;
}
publicvoid run() {
for (int i = 0; i < 5; i++) {
for (long k = 0; k < 100000000; k++) ;
System.out.println(name + ": " + i);
}
}
}
以上两种方式,推荐使用的是实现接口Runnable来创建一个线程。因为实现接口比继承Thread类灵活。
ThreadFactory
其实,创建线程还有第三种方式:ThreadFactory的方式。这是通过线程工厂的方式来创建线程。提高工厂,了解设计模式的童鞋都很清楚,工厂的作用,它就是帮助我们来创建线程的。那么什么情况下,我们需要使用到线程工厂呢?
我们需要实现线程工厂 ThreadFactory接口,然后实现工厂中唯一的方法:newThread()。这个方法就是我们要改造的东东。也是我们使用threadFactory 的目的——定制线程。在newThread()方法中,我们根据自己的需求,定制代码,同时还可以添加一些辅助的方法来定制。
例如:我们指定创建多少个线程之后就停止创建,即使再有被调用,创建新的线程,也不行。大家都明白,一个进程中的线程也不是越多越好,要根据CPU来定,本身没有那么大的能力,还有跑那么多线程,反而会拖慢线程。这就好比是一个工厂的盈利最大的时候是工厂有100个人,但是如果工厂雇佣了200个人,那么就要开始消耗盈利了。
以上就是线程创建的三种方式,我们应该在合适的适合选择合适的创建方式。
线程的执行
线程的执行 start OR run ?
刚才我们讲了run是线程运行中核心的执行方法,也就是说,启动线程后,就要执行run,那么,我们可以直接调用run吗?
我们来看看 正常的代码是如何写?
public static void main(String[] args) {
Thread t1 = new TestThread("阿三");
Thread t2 = new TestThread("李四");
t1.start();
t2.start();
}
看到,上边的代码,使用的是start()方法。这也是正确的启动 线程的途径。那么run 行吗?
答案是:不行。原因:如果直接写 t1.run();这是调用,不是开启一个线程,run只是单纯的调用run()方法。程序中不会多一个并行的线程,如果原来有 一个main线程在运行,那么现在还是一个main线程在运行;start()是 开启一个并行的线程,程序中会有两个并行的线程再走,一个main,一个是t1 线程。
属性 & 方法
属性
最后我们来说说线程的属性。线程的属性主要有这几个:线程的ID,线程的Name,线程的状态,线程的优先级。
这里的线程优先级,在并发线程的时候,我们可以通过设置线程的优先级来争取线程的CUP的资源。
方法
有这么几个方法需要知道:start,run,sleep,interrupt,yield,join。
interrupt
其中start,run不说了,我们来说说interrupt()方法。这是线程中断的方法。如果使用interrupt那么就必须截取interruptException异常。
sleep
然后是sleep 和 yield方法。sleep 和 yield都可以让一个线程暂停,且释放CPU的资源;不同的是 yield一般用在 调试代码中。
要理解yield(),必须了解线程的优先级的概念。线程总是存在优先级,优先级范围在1~10之间。JVM线程调度程序是基于优先级的抢先调度机制。在大多数情况下,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。但这仅仅是大多数情况。
join
join是等待线程运行结束。如果有多个线程同时在运行,那么使用join方法,会等待所有的线程都执行完,才开始进行后续的操作。
这写是最基本的线程的入门知识,分享到这里,下篇博客继续介绍线程组,局部线程变量的知识。
附图