目录
1.简介
线程用于同时执行多个任务,主要依靠CPU内核进行操作,主要有两种方法:
(1)并发
同一时刻,多个线程交替进行,即单核CPU进行的多任务并发操作,因为操作速度快,造成一种貌似同时进行的感觉。
(2)并行
同一时刻,多个线程同时进行,即多核CPU进行的多任务并行操作。
2.线程基本使用
(1)继承Thread类,重新run方法
创建一个用于执行线程的类,让它去继承Thread类且重写run方法,在run方法中放入要执行的操作,在需要执行该线程的线程中创建对象,并调用start()方法,即可执行该线程。
public class EatBzoZi {
public static void main(String[] args) throws InterruptedException {
T t = new T();
t.start();
for(int i = 0;i < 10;i++){
System.out.println("EAT FISH\t" + i);
Thread.sleep(1000);
if(i == 5){
t.join();
}
}
}
}
class T extends Thread{
private int i = 0;
@Override
public void run() {
while(true){
for(;i < 10;i++){
System.out.println("EAT BAO ZI\t" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
}
}
其中的Thread.sleep(1000);方法是用于让程序执行中休眠1000毫秒再去执行下一步,使用此方法会有一个异常,如果是主方法中使用,可直接抛出异常,其他方法中,可以捕获异常。
(2)实现Runnable接口,重新run方法
首先创建一个类用于实现Runnable接口,再重写run方法,这些步骤与Thread一致,唯一不同的是,Runnable中没有start()方法,若要想线程跑起来就要创建一个Thread的对象,把实现Runnable类的对象传进去便可以调用start()方法。
Hello hello = new Hello();
Hi hi = new Hi();
Thread thread = new Thread(hello);//使用Thread对象传入Runnable对象,即可调用start方法
Thread thread1 = new Thread(hi);
thread.start();
thread1.start();
3.线程的方法
(1)常用方法
(2)插队方法
yield的使用主要是在CPU不足的情况下,让其他线程优先使用CPU,如果CPU剩余充足,则不会礼让成功。
join的使用是强行插队(基本上都会插队成功),如果要使用此方法,就要在执行此线程的线程中调用该方法,假设想要在线程A中调用线程B,并且让线程B执行完后再执行线程A,那么就可以在A的代码中使用B的对象调用join方法,那就会先执行完B线程再执行A线程。
public class EatBzoZi {
public static void main(String[] args) throws InterruptedException {
T t = new T();
t.start();
for(int i = 0;i < 10;i++){
System.out.println("EAT FISH\t" + i);
Thread.sleep(1000);
if(i == 5){
t.join();//当i==5时,优先执行完T线程再执行main线程
}
}
}
}
class T extends Thread{
private int i = 0;
@Override
public void run() {
while(true){
for(;i < 10;i++){
System.out.println("EAT BAO ZI\t" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
}
}
(3)守护线程
当一个线程在其他用户线程执行完后,自动退出,那么这个线程就叫做守护线程
A a = new A();//创建A对象
a.setDaemon(true);//将a设置成守护线程,守护线程必须在启动前设置
a.start();
4.线程的生命周期
在线程的执行中有以上六种状态,具体实现如下图(非常重要)
查看当前状态的方法对象名.getState().
5.线程的同步
(1)机制
(2)同步具体方法-Synchronized
使用同步代码块时,对象锁的对象必须为几个要进行线程操作对象的相同对象,最好使用静态的Object类的对象
public class Main_ {
public static void main(String[] args) {
Balance balance = new Balance();
new Thread(balance).start();
new Thread(balance).start();
}
}
class Balance implements Runnable{
private int bal = 10000;
private int i = 0;
private static Object obj = new Object();
private boolean loop = true;
@Override
public void run() {
while (loop){
// synchronized (obj){//两种方法都可
// if (bal <= 0) {
// loop = false;
// return;
// }
// bal -= 1000;
// i++;
// System.out.println("第" + i + "次取钱,还有余额" + bal + "元");
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
method();
}
}
public synchronized void method(){
if (bal <= 0) {
loop = false;
return;
}
bal -= 1000;
i++;
System.out.println("第" + i + "次取钱,还有余额" + bal + "元");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}