Java中的多线程
线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。
多个线程的执行是并发的,也就是在逻辑上“同时”,而不管是否是物理上的“同时”。如果系统只有一个CPU,那么真正的“同时”是不可能的,但是由于CPU的速度非常快,用户感觉不到其中的区别,因此我们也不用关心它,只需要设想各个线程是同时执行即可。
多线程和传统的单线程在程序设计上最大的区别在于,由于各个线程的控制流彼此独立,使得各个线程之间的代码是乱序执行的,需要有线程调度,同步等问题。
2.Java中实现多线程的方法
(1).继承 Thread 类,覆盖方法 run(),我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可
public class MyThread extends Thread
{
int count= 1, number;
public MyThread(int num)
{
number = num;
System.out.println
("创建线程: " +number);
}
public void run() {
while(true) {
System.out.println
("线程 :" +number +" 计数: " count);
if( count== 6) return;
}
}
public static void main(String args[])
{
for(int i = 0; i〈 5; i++ )
new MyThread(i).start();
}
}
上面是实现多线程的一种方式,但是它有个缺点:那就是如果我们的类已经从一个类继承(如小程序必须继承自 Applet 类),则无法再继承 Thread 类,这时如果我们又不想建立一个新的类,应该怎么办呢,只能使用方法二了;
(2).实现 Runnable 接口
Runnable接口只有一个方法run(),我们声明自己的类实现Runnable接口并提供这一方法,将我们的线程代码写入其中,就完成了这一部分的任务。但是Runnable接口并没有任何对线程的支持,我们还必须创建Thread类的实例,这一点通过Thread类的构造函数public Thread(Runnable target);来实现
示例程序:
public class MyThread implements Runnable
{
int count= 1, number;
public MyThread(int num)
{
number = num;
System.out.println("创建线程: "+ number);
}
public void run()
{
while(true)
{
System.out.println
("线程 " +number +" 计数: "+ count);
if( count== 6) return;
}
}
public static void main(String args[])
{
for(int i =0; i<5;i++ ) new Thread(new MyThread(i)).start();
}
}
使用 Runnable 接口来实现多线程使得我们能够在一个类中包容所有的代码,有利于封装,它的缺点在于,我们只能使用一套代码,若想创建多个线程并使各个线程执行不同的代码,则仍必须额外创建类,如果这样的话,在大多数情况下也许还不如直接用多个类分别继承 Thread 来得紧凑。
3.线程的生命周期
(1)start()方法 启动一个线程
(2)run()方法 定义该线程的动作
(3)sleep()方法 使线程睡眠一段时间,单位为毫秒
(4)suspend()方法 使线程挂起
(5)resume()方法 恢复挂起的线程
(6)yield()方法 把线程移到队列的尾部
(7)stop()方法 结束线程生命周期并执行清理工作
(8)destroy()方法 结束线程生命周期但不做清理工作
其中最常用的是start(),run(),sleep(),stop()。
4.线程的四种状态
(1). 新状态:线程已被创建但尚未执行(start() 尚未被调用)。
(2). 可执行状态:线程可以执行,虽然不一定正在执行。CPU 时间随时可能被分配给该线程,从而使得它执行。
(3). 死亡状态:正常情况下 run() 返回使得线程死亡。调用 stop()或 destroy() 亦有同样效果,但是不被推荐,前者会产生异常,后者是强制终止,不会释放锁。
(4). 阻塞状态:线程不会被分配 CPU 时间,无法执行
5.线程的优先级
线程的优先级低并不是意味着线程得不到执行,优先级低只是执行的频率比较低吧
你可以调用 Thread 类的方法 getPriority() 和 setPriority()来存取线程的优先级,线程的优先级界于1(MIN_PRIORITY)和10(MAX_PRIORITY)之间,缺省是5(NORM_PRIORITY)。
package MyJava_Base;
class myThread extends Thread
{
private String name;
int priority;
myThread(String name,int priority)
{
this.name=name;
this.setName(name);
this.priority=priority;
this.setPriority(priority);
}
public void run()
{
System.out.println("线程启动/t名称: "+this.getName()+"/t 优先级: "+this.getPriority());
}
}
public class testThreadPriority
{
public static void main(String[] args)
{
myThread t1=new myThread("A",3);
myThread t2=new myThread("B",5);
myThread t3=new myThread("C",9);
t1.start();
t2.start();
t3.start();
try
{
t1.join();
t2.join();
t3.join();
}catch(InterruptedException e)
{
System.out.println("Error:"+e);
}
}
}
6.后台线程(守护线程):
守护线程是一类特殊的线程,它和普通线程的区别在于它并不是应用程序的核心部分,当一个应用程序的所有非守护线程终止运行时,即使仍然有守护线程在运行,应用程序也将终止,反之,只要有一个非守护线程在运行,应用程序就不会终止。守护线程一般被用于在后台为其它线程提供服务。
可以通过调用方法 isDaemon() 来判断一个线程是否是守护线程,也可以调用方法 setDaemon() 来将一个线程设为守护线程