什么是多线程
最近在学习java的多线程运行机制,才发下之前在学习android的时候已经接触到了多线程,但是当时并没有太在意,这次学习多线程算是一个复习吧。
首先,要理解好线程与进程之间的关系,一个应用程序就是一个进程,而一个进程里面可以有多个线程。举个例子,选课系统中,每个学生选的课都不一样,每个学生就是一个线程,或者像买电影票一样,一个客户就是开了一个线程。为什么要分不同的线程呢?这个也很好理解,因为一个应用程序不可能只为一个人运行,那么多个人同事运行的话就是为了防止某个资源的过度占用,为了让每个客户都可以正常买票,所以必须开启多线程。
如何实现多线程
实现多线程有两种方法:
第一种继承Thread类,第二种是实现Runablie接口。但是实际上,Thread类也是实现了Runable接口,所以两种方法实际上都是通过接口来实现了。但是两者也是有差别的。
如何通过继承Thread来实现多线程
继承Thread类来实现多线程是将线程内容写在约定方法run()中,在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。需要注意的是,实现了start()方法后,线程不是马上就运行了,而是变为可运行状态,具体什么时候运行是随机的,由系统决定的。
public class MyThread extends Thread{
private String name;
public MyThread(String name) {
this.name=name;
}
public void run() {
for(int i=1;i<5;i++)
System.out.println(name+"第"+i+"次运行");
}
}
public class Main {
public static void main(String[] args) {
// TODO 自动生成的方法存根
MyThread mth1=new MyThread("A");
MyThread mth2=new MyThread("B");
new Thread(mth1).start();
new Thread(mth2).start();
}
}
运行结果为:
A第1次运行
A第2次运行
A第3次运行
A第4次运行
B第1次运行
B第2次运行
B第3次运行
B第4次运行
很明显,他的运行顺序是随机的。
如何通过实现Runnable来实现多线程
实现Runnable的接口实际上也是类似,需要在run()方法中实现线程的代码
public class MyThread implements Runnable{
private String name;
public MyThread(String name) {
this.name=name;
}
@Override
public void run() {
// TODO 自动生成的方法存根
for(int i=1;i<5;i++)
System.out.println(name+"第"+i+"次运行");
}
}
public class Main {
public static void main(String[] args) {
// TODO 自动生成的方法存根
MyThread mth1=new MyThread("A");
MyThread mth2=new MyThread("B");
new Thread(mth1).start();
new Thread(mth2).start();
}
}
运行的结果也与刚才相似:
B第1次运行
A第1次运行
B第2次运行
A第2次运行
B第3次运行
A第3次运行
B第4次运行
A第4次运行
这里看到,两次代码块其实都是一样的,但是运行的结果却不一样,这也更好说明了java的运行顺序是随机的。
Thread类与Runnable接口的区别
Runnable是可以进行资源共享的,即当买票的时候,剩余多少张票应该对于每一个用户都是共享的变量,这个时候就可以用Runnable接口进行资源的共享
public class share implements Runnable{
private int count=15;
@Override
public void run() {
// TODO 自动生成的方法存根
for(int i=5;i>0;i--)
System.out.println(Thread.currentThread().getName()+"运行"+count--);
}
}
```public class Main {
public static void main(String[] args) {
// TODO 自动生成的方法存根
share sh=new share();
new Thread(sh,"A").start();;
new Thread(sh,"B").start();;
new Thread(sh,"C").start();;
}
}
运行结果为:
A运行15
C运行13
A运行12
B运行14
C运行11
A运行9
C运行8
C运行6
B运行10
C运行5
A运行7
B运行4
A运行3
B运行2
B运行1
可见,count变量在A,B,C线程中是共享的,这点就是Thread与Runnable的区别。