多线程一:两种方式实现多线程
多线程一:两种方式实现多线程
一.解析多线程:
A.通俗语言(和程序中的线程有一些出入):
一个公司的经理手上有一个项目【一个java项目】,安排他的员工【Java中的方法】同时完成这个项目。
此时,这个经理也是干活的,不是闲着的,也就是,他是【主线程】,他的员工是【子线程】。
此时,这项工程就不是经理一个人在做了,也就是不是顺序执行了,也就是多线程操作。
B.java解析:
同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
在介绍线程时,有一个非常重要的概念,是“进程”。
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)
☆通俗语言和java解析的不同之处:表现在这个“同时”,现实中真的能做到同时做一个工程,但是程序中,由于系统的限制,它的“同时”是CPU频繁的”切换得结果”,由于切换得频率过快,给人一种错觉上的“同时”。
整个项目图:
二.多线程实现案例:
1.顺序执行案例(单线程,它是按着程序的先后顺序走的):
package thread;
class OrderThread {
public void run() {
while (true) {
System.out.println("线程学习");
}
}
public void start() {
run();
}
}
public class Thread0 {
public static voidmain(String[] args) {
newOrderThread().start();
;
}
}
2.通过继承Thread实现多线程:
1.源代码:
package thread;
/**
* 通过继承Thread实现多线程技术
*
*/
/*
* 通过继承实现Thread需要以**意项: 第一步:继承Thread 第二步:重写run()方法 第三步:实例化本类 第四步:调用start方法,启动线程
*/
class MyThread extends Thread { // 线程一(子线程) 1.继承Thread
@Override
public void run() { // 2.重写run()方法
for (int i = 0; i< 10; i++) {
// 设置当前线程名
System.out.println(Thread.currentThread().getName());// 输出当前线程名
}
}
}
public class Thread1 {
public static voidmain(String[] args) { // 线程0(主线程)
for (int i = 0; i< 10; i++) {
System.out.println(Thread.currentThread().getName());
}
// 3.实例化本类
MyThread t1 = newMyThread();
MyThread t2 = newMyThread();
// 设置当前线程名(它也有自己默认的线程名)
t1.setName("线程1");
t2.setName("线程2");
// 4.调用start方法
t1.start();
t2.start();
}
}
2.运行结果:
3.通过实现Runable接口实现多线程
1.源代码:
package thread;
/**
* 通过实现Runnable接口实现多线程技术
*/
/*
* 通过实现Runnable需要以**意项: 第一步:实现Runnable接口 第二步:实现run()方法 第三步:实例化本类
* 第四步:实例化当前类 第五步:实例化Thread 第六步:将当前类以参数形式传入Trhead,调用start方法,启动线程
*/
class MyThread2implements Runnable{ //1:实现Runnable接口
@Override
public void run() { //2.实现run()方法
for (int i = 0; i < 200; i++) {
// 设置当前线程名
System.out.println(Thread.currentThread().getName());// 输出当前线程名
}
}
}
public classThread2 {
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName());
}
MyThread2 t1=new MyThread2(); //3.实例化本类
new Thread(t1,"线程一").start(); //4:实例化当前类 5:实例化Thread 6:将当前类以参数形式传入Trhead,调用start方法,启动线程
new Thread(t1,"线程二").start();;
}
}
2.运行结果:
3.解析:
1.多线程的运行结果是不固定的,因为它的调用顺序是随机的。
2.本实例中一共有三个线程,分别为主线程,线程一,线程二。一个程序中可以没有子线程,但是主线程是必须的。
三.两种线程实现的比较
从main函数入手,分别参考下面截图:
1.继承Thread
2.实现Runnable
第一种是把当前类实例化了两次,启动了两个线程。
第二种是把当前类实例化了一次,启动了两个线程。
所以,第一种是对象资源独立性的,第二种是对象资源”共享性”的。
于是:如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
于是,实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
四.特别注意:
1.main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。
2.在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。
参考资料:http://blog.****.net/evankaka/article/details/44153709#t0
本内容由安康学院"雨季"原创!