Java多线程-线程的同步
Java语言使用多线程实现一个程序中的多个任务同时运行,程序员可以在程序中执行多个线程,每个线程完成一个功能,并与其他线程并发执行,这种机制成为多线程。(并发,事实上在同一个时间点上只有一个线程被执行,只是线程之间的切换比较快,才会产生线程是同时进行的假象。)
在学习java多线程之前先了解下程序,进程,线程的关系。
程序是一段静态的代码,它是应用程序执行的蓝本。进程是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。线程是比进程更小的单位,一个进程执行过程中可以产生多个线程,每个线程有自身的产生、存在和消亡的过程,也是一个动态的概念。每个进程都有一段专用的内存区域,而线程间可以共享相同的内存区域(包括代码和数据),并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。
每个Java程序都有一个默认的主线程。Java程序总是从主类的main方法开始执行。当JVM加载代码,发现main方法后就启动一个线程,这个线程就称作"主线程",该线程负责执行main方法。在main方法中再创建的线程就是其他线程。如果main方法中没有创建其他线程,那么当main方法返回时JVM就会结束Java应用程序。但如果main方法中创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法返回(主线程结束)JVM也不会结束,要一直等到该程序所有线程全部结束才结束Java程序(另外一种情况是:程序中调用了Runtime类的exit方法,并且安全管理器允许退出操作发生。这时JVM也会结束该程序)。
java中要实现多线程,有两种方法:(1)继承Thread类。(2)实现Runable接口。
对于直接继承Thread的类来说,代码大致框架是:
public class 类名 extends Thread{
public void run(){
//编写业务代码
}
}
注:主线程是从main()方法开始运行的,但Thread类的线程对象是从run()方法开始执行的,所以继承Thread类之后,需要重写run()方法,在该方法中实现自己的业务处理。Thread类的start()方法用于启动一个线程对象,线程对象调用start()方法后java虚拟机启动该线程对象,并调用该线程的run()方法执行业务代码。
先看一个简单的例子:
public class
Hello
extends
Thread {
private
String name;
public
H
ello(String name) {
this
.name = name;
}
public
void
run() {
for
(
int
i =
0
; i <
5
; i++) {
System.out.println(name +
"运行 "
+ i);
}
}
public
static
void
main(String[] args) {
H
ello h1=
new
H
ello(
"A"
);
H
ello h2=
new
H
ello(
"B"
);
h1.start();
h2.start();
}
}
【运行结果】:
B运行 0
A运行 1
B运行 1
B运行 2
A运行 2
A运行 3
A运行 4
B运行 3
B运行 4
注意:虽然我们在这里调用的是start()方法,但是实际上调用的还是run()方法的主体。那么我们为什么不直接调用run()方法呢?原因:线程的运行需要本地操作系统的支持。
对于通过实现Runable接口的方法,大致框架如下:
public class 类名 implements Runnable{
public void run(){
//业务处理代码
}
}
示例如下:
public class HelloRunnable implements Runnable{
private
String name;
public
HelloRunnable (String name) {
this
.name = name;
}
public
void
run() {
for
(
int
i =
0
; i <
5
; i++) {
System.out.println(name +
"运行 "
+ i);
}
}
public
static
void
main(String[] args) {
HelloRunnable
h1=
new
HelloRunnable (
"线程A"
);
Thread demo=
new
Thread(h1);
HelloRunnable
h2=
new
HelloRunnable (
"线程B"
);
Thread demo1=
new
Thread(h2);
demo.start();
demo1.start();
}
}线程B运行 0
线程A运行 1
线程B运行 1
线程B运行 2
线程B运行 3
线程A运行 2
线程B运行 4
线程A运行 3
线程A运行 4
Thread和Runnable的区别:
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
总结一下:
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。