初识多线程(理解)
(1)多线程:一个应用程序有多条执行路径
进程:
- 1.正在执行的应用程序,是系统进行资源分配和调用的独立单位。
- 2.每一个进程都有它自己的内存空间和系统资源。
线程:
- 1.是进程中的单个顺序控制流,是一条执行路径。
- 2.一个进程如果只有一条执行路径,则称为单线程程序。
- 3.一个进程如果有多条执行路径,则称为多线程程序。
单线程:一个应用程序只有一条执行路径。
多线程:一个应用程序有多条执行路径。
并行和并发:
前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。
后者是物理上同时发生,指在某一个时间点同时运行多个程序。
Java程序的运行原理:
由java命令启动JVM,JVM启动就相当于启动了一个进程。
接着有该进程创建了一个主线程去调用main方法。
多进程的意义?
答:提高CPU的使用率。
多线程的意义?
答:提高应用程序的使用率。程序的执行其实都是在抢CPU的资源,CPU的执行权。
多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的几率抢
到CPU的执行权。我们是不敢保证哪一个线程能够在哪个时刻抢到,所以线程的执行有随机性。
(2)Java程序的运行原理及JVM的启动是多线程的吗?
答:是多线程的。
原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。
现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,jvm的启动其实是多线程的。
(3)多线程的实现方案(自己补齐步骤及代码 掌握)
A:继承Thread类
步骤:
1:自定义类MyThread继承Thread类;
2:MyThread类里面重写run();
3:创建对象;
4:启动线程.
public class MyThread extends Thread {
@Override
public void run() {
// 自己写代码
// System.out.println("好好学习,天天向上");
// 一般来说,被线程执行的代码肯定是比较耗时的。所以我们用循环改进
for (int x = 0; x < 200; x++) {
System.out.println(x);
}
}
}
该类要重写run()方法,为什么呢?
不是类中的所有代码都需要被线程执行的。
而这个时候,为了区分哪些代码能够被线程执行,java提供了Thread类中的run()用来包含那些被线程执行的代码。
B:实现Runnable接口
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
// 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}
步骤:
1:自定义类MyRunnable实现Runnable接口;
2:重写run()方法;
3:创建MyRunnable类的对象;
4:创建Thread类的对象,并把C步骤的对象作为构造参数传递.
(4)线程的调度和优先级问题
1:线程的调度
a:分时调度.
b:抢占式调度 (Java采用的是该调度方式).
2:获取和设置线程优先级
a:默认值是5.
b:范围是MIN_PRIORITY(1)~MAX_PRIORITY(10).
(5)线程的控制(常见方法)
- A:休眠线程 public static void sleep(long millis)
- B:加入线程 public final void join()
- C:礼让线程 public static void yield()
- D:守护线程 public final void setDaemon(boolean on)
- E:终止线程(掌握) public void interrupt()
(6)线程的生命周期
描述线程的生命周期?
新建:创建线程对象。
就绪:有执行资格,没有执行权。
运行:有执行资格,有执行权。
阻塞:由于一些操作让线程处于了该状态。没有执行资格,没有执行权。
而另一些操作却可以把它重新激活,激活后处于就绪状态。
死亡:线程对象变成垃圾,等待被回收。
(7)同步的特点:
前提:
多个线程
解决问题的时候要注意:
多个线程使用的是同一个锁对象。
同步的好处:
同步的出现解决了多线程的安全问题。
同步的弊端:
当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。
(9)多线程安全问题的原因(也是我们以后判断一个程序是否有线程安全问题的依据)
1:是否有多线程环境
2:是否有共享数据
3:是否有多条语句操作共享数据
(10)同步解决线程安全问题
A:同步代码块
同步代码块的锁对象是谁呢?
任意对象。
synchronized(对象) {
需要被同步的代码;
}
//这里的锁对象可以是任意对象。
B:同步方法
把同步关键字加在方法上。
这里的锁对象是this
C:静态方法
静态方法及锁对象问题?
静态方法的锁对象是谁呢?
类的字节码文件对象。(反射会讲)
(11)回顾以前的线程安全的类
A:StringBuffer
B:Vector
C:Hashtable
D:如何把一个线程不安全的集合类变成一个线程安全的集合类
用Collections工具类的方法即可。
List<String> list1 = new ArrayList<String>();// 线程不安全
List<String> list2 = Collections
.synchronizedList(new ArrayList<String>()); // 线程安全