1、线程简介
进程:正在执行的应用程序
线程:进程的执行单元,执行路径
单线程:一个应用程序只有一条执行路径
多线程:一个应用程序有多条执行路径
多进程的意义:提高CPU的使用率
多线程的意义:提高应用程序的使用率
在我们的生活中,可以同时完成很多工作。例如,人体可以同时进行呼吸,血液循环,思考问题等活动,用户既可以使用电脑听歌,也可以使用它聊天,而这些活动完全可以同时进行,这种思想在Java中称为并发,而将并发完成的每一件事情称为线程。
在Java中,并发机制非常重要,但并不是所有的程序语言都支持线程。在以往的程序中,多以一个程序完成后再进行下一个项目的模式进行开发,这样下一个任务的开始必须等待前一个任务的结束。Java语言提供了并发机制,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程。
2、实现线程的两种方式
在Java中主要提供两种方式实现线程,分别为继承java.lang.Thread类与实现java.lang.Runnable接口。
(1)继承Thread类
public class ThreadTest extends Thread{
@Override
public void run() {
for (int i = 0; i <5 ; i++) {
System.out.println("你好啊"+i);
}
}
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
threadTest.start();
}
}
(2)实现Runnable接口
public class ThreadTest2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("你好啊"+i);
}
}
public static void main(String[] args) {
ThreadTest2 threadTest2 = new ThreadTest2();
Thread thread = new Thread(threadTest2);
thread.start();
}
}
3、线程的调度和优先级问题
A:线程的调度
a:分时调度
b:抢占式调度 (Java采用的是该调度方式)
B:获取和设置线程优先级
a:默认是5
b:范围是1-10
4、线程的常见方法
- setPriority(int newPriority):更改线程的优先级
- static void sleep(long millis):在指定的毫秒数内让当前正在执行的线程休眠
- void join():等待该线程终止
- static void yield():暂停当前正在执行的线程对象,并执行下一个线程
- void interrupt():中断线程
- boolean isAlive():测试线程是否处于活动状态
5、线程的生命周期
线程具有生命周期,其中包含七种状态,分别为出生状态,就绪状态,运行状态,等待状态,休眠状态,阻塞状态和死亡状态。出生状态就是线程被创建时处于的状态,在用户使用该线程实例调用start()方法之前线程都处于出生状态;当用户调用start()方法后,线程处于就绪状态;当线程得到系统资源后就进入运行状态。
一旦线程进入可执行状态,它会在就绪与运行状态下转换,同时也有可能进入等待,休眠,阻塞或死亡状态。当处于运行状态下的线程调用Thread类中的wait()方法时,该线程便进入等待状态,进入等待状态的线程必须调用Thread类中的notify()方法才能被唤醒,而notifyAll()方法是将所有处于等待状态下的线程唤醒;当线程调用Thread类中的sleep()方法时,则会进入休眠状态。如果一个线程在运行状态下发出输入/输出请求,该线程就进入阻塞状态,在其等待输入/输出结束时线程进入就绪状态,对于阻塞的线程来说,即使系统资源空闲,线程依然不能回到运行状态。当线程的run()方法执行完毕时,线程进入死亡状态。
6、线程同步
在单线程程序中,每次只能做一件事情,后面的事情需要等待前面的事情完成后才可以进行,但是如果使用多线程程序,就会发生两个线程抢占资源的问题,如果两个人同时说话,两个人同时过同一个独木桥等。所以在多线程编程中需要防止这些资源访问的冲突。Java提供了线程同步的机制来防止资源访问的冲突。7、线程安全
电影院买票问题
public class ThreadSafe implements Runnable {
//定义十张票
int tickets=10;
@Override
public void run() {
while (true) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("还有" + tickets-- + "张票");
}
}
}
public static void main(String[] args) {
ThreadSafe threadSafe = new ThreadSafe();
Thread thread1 = new Thread(threadSafe);
Thread thread2 = new Thread(threadSafe);
Thread thread3 = new Thread(threadSafe);
thread1.start();
thread2.start();
thread3.start();
}
}
运行实例,最后结果为:
看结果,发现了问题
- 出现了负票
- 出现了同票多次
多线程出现安全问题的原因(也是我们以后判断一个程序是否有线程安全问题的依据)
A:是否有多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
)同步解决线程安全问题
A:同步代码块
synchronized(对象) {
需要被同步的代码;
}
这里的锁对象可以是任意对象。
B:同步方法
public synchronzed void doit(){
需要被同步的代码
}
把同步加在方法上。
这里的锁对象是this