线程:并发安全性问题:
一:线程概述:
1:进程:
学习线程之前,我们必须要知道什么是进程。
进程是计算机中特定功能的程序再数据集上的一次运行。如,我们现在打开的word软件这就是一个进程。
2:线程:
线程是进程的一个单元,一个运行中的进程,内部可能有多个线程。也就是说线程要比进程的粒度小。
如:音乐播放器,一次只能播放一首歌,这首歌播放完毕后,才可以播放下一首,这就是一个进程中有一个线程。这种叫做单线程进程。
但是往往很多的进程都是包含多个线程的,如我们使用迅雷下载视屏,可以同时下载多部电影,迅雷软件的一次运行,就是一个进程,每一部电影的下载,都是一个线程,同时下载多部电影,就是多线程进程。
我们的qq,微信,可以同时和多个人交流,这也是多线程。
我们java虚拟机运行的时候,主函数其实就是一个线程,java虚拟机是多线程的,如在堆中,有些对象不再使用了,就需要通过垃圾回收机制的线程来回收没有用的对象,垃圾回收机制的线程在主函数的线程运行的时候,垃圾回收机制的线程在后台其实也是在运行着的,只不过我们没有看到,这里又是一个线程。由此java虚拟机是多线程的。
二:线程创建:
线程的实现,在我们java中,有一个专门创建线程的类:Thread
创建新执行线程有两种方法。一种方法是将类声明为 Thread
的子类。该子类应重写Thread
类的 run
方法。接下来可以分配并启动该子类的实例。
创建线程的另一种方法是声明实现 Runnable
接口的类。该类然后实现 run
方法。然后可以分配该类的实例,在创建 Thread
时作为一个参数来传递并启动
Run中是线程体,每一个线程执行的时候,执行的都是run中的代码。
获得线程的名字
启动线程:我们不能通过run方法去启动线程
方式一:
/*
* 创建线程的方式一:创建一个类,这个类继承Thread这个类,并且实现
* Thread中的run方法
*/
public class ThreadDemo extends Thread{
public static void main(String[] args) {
//启动线程,创建线程的实例对象
ThreadDemo td = new ThreadDemo();
//由于是多线程,我可以创建多个线程的实例对象
ThreadDemo td1 = new ThreadDemo();
/*
* 线程的名字除了可以获得之外,我们也可以自己设置线程的名字,我们没有设置名字的时候。java虚拟机会为每一个
* 线程分配一个名字
*/
td.setName("线程1");
td1.setName("线程2");
/*
* 分别启动两个线程,首先我们是要让run方法运行起来,但是我们不能直接通过实例去调run方法,
* 如果我直接去调用run方法的话,这不是启动线程,这里就是单纯的调用run方法,这是没有任何意义的。
*/
/*td.run();
td1.run();*/
/*
* 启动线程,这样启动线程,连个线程会同时去执行,不会等到线程0一个线程执行完,再去执行另一个线程。
* 这里两个线程会同时去执行
*/
td.start();
td1.start();
/*
* 当我执行到这里的时候,总共有三个线程在运行,主函数不能忽视
*/
}
/*
* 重写Thread中run方法,run方法中就是线程的执行体
*/
@Override
public void run() {
//编写线程体
for(int i = 0; i < 30;i++){
//为了区分每一个线程,我可以获得每一个线程的名字
System.out.println(this.getName()+"---线程---"+i);
}
}
}
public class ThreadDemo1 extends Thread{
private String tName;
public ThreadDemo1() {
}
public ThreadDemo1(String tName) {
super(tName);
}
@Override
public void run() {
for(int i = 0; i < 30;i++){
System.out.println(this.getName()+"---线程---"+i);
}
}
}
public class Test {
public static void main(String[] args) {
Threa