Java SE入门(二十二)——多线程
iwehdio的博客园:https://www.cnblogs.com/iwehdio/
1、多线程
进程:当前正在运行的程序,即一个应用程序在内存中的执行区域。
线程:进程中的一个执行控制单元。一个进程可以有一个线程,也可以有多个线程。
单线程:安全性高但是效率低。多线程:安全性低但是效率高。
CPU执行线程具有随机性。
多线程的实现方式1 :Thread 类。
- 写一个子类,继承 Thread 类。
- 在子类中重写 Thread 类的 run 方法,内容是线程的操作内容。
- 创建线程实例。
- 使用
.start()
方法启动线程。
public class MyThread extends Thread { @Override public void run(){ System.out.println("线程"); System.out.println(getName()); } } MyThread mt = new MyThread(); mt.setName("线程A"); mt.start();
Thread 类中的方法:
String getName()
:获取线程的名字。void setName(String name)
:改变线程名字。static Thread currentThread()
:返回对当前正在执行的线程对象的引用。static void sleep(long millis)
:将线程休眠一段时间。
主方法是单线程的。
多线程的实现方式2 :实现 Runnable 接口。
- 写一个子类,实现 Runnable 接口。
- 在子类中重写 run 方法,内容是线程的操作内容。
- 创建线程实例,并将其作为参数传入 Thread 对象。
- 使用
.start()
方法启动线程。
public class MyThread implements Runnable { @Override public void run(){ System.out.println("线程"); System.out.println(Thread.currentThread().getName()); } } MyThread mt = new MyThread(); // 可以只创建一个,但是所有 Thread 对象会共享成员变量 Thread t1 = new Thread(mt); // 将实现的接口的对象作为参数传入 t1.setName("线程A"); t1.start(); Thread t2 = new Thread(mt); t2.setName("线程B"); t2.start();
为什么多线程需要第二种方法的接口实现:因为 Java 中单一继承的原因,继承了 Thread 类就无法继承其他类。
线程的生命周期:
- 新建:创建线程对象。
- 就绪:具备了执行条件,但没有执行权利。
- 运行:具备了执行权利。
- 死亡:作为垃圾回收。
- 等待与唤醒:
void wait()
:使当前线程等待。void notify()
:唤醒等待的线程。需要使用锁对象调用,调用线程被唤醒后先进入就绪状态。
2、同步
多个线程共享同一个数据并且并发访问共享的数据,可能会出错。
synchronized
关键字:表示同步,可以修饰代码块和方法。被修饰的代码块和方法一旦被某个线程访问,则直接锁住,其他线程无法访问。同步代码块:
synchronized(锁对象){ // 执行代码 }
同步方法:
private synchronized void method(){ // 执行代码 }
锁对象需要被所有的线程所共享,非静态同步方法的锁对象默认为 this ,静态同步方法的锁对象默认为当前类的字节码对象。
同步:安全性高,效率低。
3、分票案例
public class Ticket implements Runnable{
int tickets = 100;
Object obj = new Object();
@Override
public void run(){
while(true){
method();
}
}
public synchronized void method(){
if(tickets > 0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + tickets--);
}
}
}
public class Demo {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread td1 = new Thread(t);
td1.setName("A");
Thread td2 = new Thread(t);
td2.setName("B");
Thread td3 = new Thread(t);
td3.setName("C");
td1.start();
td2.start();
td3.start();
}
}
iwehdio的博客园:https://www.cnblogs.com/iwehdio/