一、基本概念
- 进程:一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
- 线程:操作系统中能够进行运算的最小单位,它被包含在进程之中,是进程中的实际运作单位。(简单理解:应用软件中相互独立,可以同时运行的功能)
- 多线程:
作用:提高效率
应用场景:多件事情同时运行
3.并发和并行:
- 并发:在同一时刻,有多个指令在CPU上交替执行
- 并行:在同一时刻,有多个指令在CPU上同时执行
二、多线程实现方法
1.继承Thread类
-
创建继承Thread的子类
-
重写Thread类的run()方法
-
创建Thread类的子类的对象。
-
通过此对象调用start()来启动一个线程。
public class MyThread extends Thread {
public void run(){
for (int i = 0; i < 100; i++) {
System.out.println(getName()+"HelloWord");
}
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start();
t2.start();
}
}
2.实现Runnable接口
- 定义一个类实现Runnable接口
- 重写里面的Run()方法
- 创建自己的类的对象
- 创建一个Thread类的对象调用start(),开起线程
public class RunnableThread {
public static void main(String[] args) {
MyRun mr = new MyRun();
Thread t1 = new Thread(mr);
t1.start();
Thread t2 = new Thread(mr);
t2.start();
}
}
class MyRun implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println(Thread.currentThread().getName()+":/t"+i);
}
}
}
3.利用Callable接口和Future接口(特点:可以获取到多线程运行的结果)
-
创建一个类MyCallable实现callable接重写call (是有返回值的,表示多线程运行的结果)
-
创建MyCallable的对象(表示多线程要执行的任务)
-
创建FutureTask的对象(作用管理多线程运行的结果)
-
创建Thread类的对象,并启动(表示线程)
三种方式对比:
三、常见的成员方法
四、线程的生命周期
线程的动态特征表明:它由创建而生,由调度而执行,由撤销而消亡。说明线程具有一个从生到死的生命周期。
新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
就绪:处于新建状态的线程被start()后,将进入线程队列等待cpu时间片,此时它已经具备了运行的条件
运行:当就绪的线程被调度并获得处理器资源时,便进入运行状态,run()方法定义了线程的操作和功能
阻塞:在某种特殊情况下,被人为挂起或者执行输入输出操作时,让出cpu并临时终止你自己的执行,进入阻塞状态
死亡:线程完成了它的全部工作或线程被提前强制性地中止
五、多线程安全性问题的解决
如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。 程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。 线程安全问题都是由全局变量及静态变量引起的。 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
解决方法:
1.同步代码块
- 将操作共享的代码锁起来
- 锁默认打开,有一个线程进去了,锁自动关闭
- 里面的代码全部执行完毕,线程出来,锁自动打开
public class MyThread extends Thread {
static int a = 0;
static Object obj = new Object();
public void run(){
while(true){
synchronized (obj){
if(a<100){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
a++;
System.out.println(getName()+"卖第"+a);
}
else
break;
}
}
}
}
public class Test {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
2.同步方法:
- 将 synchronized关键字加在方法上
- 锁住方法里的所有代码
- 锁对象不能自己制定
- 非静态的同步方法,同步监视器是:this
- 静态的同步方法,同步监视器是:当前类的字节码文件对象
- 格式: