线程、线程匿名内部类、解决线程不安全的方式
线程
线程:正在运行的程序,是程序的执行路径;多线性
进程:是应用程序的载体,程序运行在虚拟机中。一个应用软件对应一个进程。
一个进程包含多个线程,一个线程对应一个进程。
好处:提高软件的运行效率
多线程的运行原理
在同一时刻只能有一个线程正在使用CPU,操作系统设计了CPU的调度方式。
- 分时调用:平均分配使用CPU的使用时间
- 抢占式调度:根据线程的优先级分配CPU资源
开发多线程的方式
- 继承Thread类
- 实现Runnable接口
Thread类
构造方法:
成员方法:
- int getPriority() 返回线程的优先级。
- String getName() 返回该线程的名称。
- void run()运行线程逻辑的代码
- void start()开启线程,使线程处于就绪状态,等待CPU的调度。
线程使用
定义子线程类(继承Thread或者实现Runable接口),重写run()方法。
创建线程对象,调用start()方法。
子线程
public class DemoThread extends Thread {
public DemoThread(){}
public DemoThread(String name){
super(name);
}
@Override
public void run() {
Thread demo = Thread.currentThread();
String demoName = demo.getName();
System.out.println(demoName);
}
}
主线程
public class DemoMain {
public static void main(String[] args) {
Thread main = Thread.currentThread();
String mainName = main.getName();
System.out.println(mainName);
//创建子线程的对象
DemoThread dt=new DemoThread("我是子线程");
dt.start();
System.out.println("主线程");
}
}
实现Runnable接口
- 定义类实现Runnable接口,重写run()方法(线程执行的代码)
- 创建子线程任务对象
- 创建子线程对象
- 调用start()方法。
子线程
public class DemoRunable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
主线程
public class MainRunnable {
public static void main(String[] args) {
//创建子任务
DemoRunable dr=new DemoRunable();
//创建子线程对象
Thread td=new Thread(dr,"子线程");
td.start();
}
}
两种方式的区别
- 继承Thread类, 任务与子线程代码 耦合(关联性)到一起。
- 实现Runnable接口,把任务代码和子线程的代码分开(解耦性强)
- 继承扩展性差、不能继承其他的父类,只能继承一个父类。
线程匿名内部类使用
/**
*只调用一次线程
* @author YandeHu
*
*/
public class DemoInner {
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
System.out.println("Thread继承子线程匿名内部类的代码");
}
}.start();
Runnable r=new Runnable(){
@Override
public void run() {
System.out.println("Runnable1 匿名自内部对象");
}
};
Thread td=new Thread(r);
td.start();
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("Runnable2 匿名自内部对象");
}
}).start();
}
}
解决线程不安全的方式
保证修改共享数据的代码在同一时刻只能一个线程访问,保证线程是同步的。
使用同步代码块
- 使用关键字 syncronized 修改共享代码块
- 同步:代码一行一行的往下执行
- 异步:多个线程同时执行
- 锁对象:任意的对象类型 ,只有线程拿到此对象,才能执行代码。
public class TiketRunnable implements Runnable {
int tiketNumber=100; //锁对象 只有获得锁对象的线程才可以执行 Object obj=new Object(); @Override public void run() { while(true){ synchronized (obj) { if(tiketNumber>0){ try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("线程"+Thread.currentThread().getName()+" 正在卖"+(tiketNumber--)+"张票"); } } } } }
Lock接口
Lock lock=new ReentrantLock();
//重写run方法
public void run() {
lock.lock();
同步代码
lock.unlock();
}
Lock lock=new ReentrantLock();
@Override
public void run() {
while(true){
lock.lock();
if(tiketNumber>0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName()+" 正在卖"+(tiketNumber--)+"张票");
}
lock.unlock();
}