线程、线程匿名内部类、解决线程不安全的方式

线程

线程:正在运行的程序,是程序的执行路径;多线性

进程:是应用程序的载体,程序运行在虚拟机中。一个应用软件对应一个进程。

一个进程包含多个线程,一个线程对应一个进程。

好处:提高软件的运行效率

多线程的运行原理

在同一时刻只能有一个线程正在使用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接口

  1. 定义类实现Runnable接口,重写run()方法(线程执行的代码)
  2. 创建子线程任务对象
  3. 创建子线程对象
  4. 调用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();
    }
}

两种方式的区别

  1. 继承Thread类, 任务与子线程代码 耦合(关联性)到一起。
  2. 实现Runnable接口,把任务代码和子线程的代码分开(解耦性强)
  3. 继承扩展性差、不能继承其他的父类,只能继承一个父类。

线程匿名内部类使用

/**
 *只调用一次线程
 * @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();
    }
}

解决线程不安全的方式

保证修改共享数据的代码在同一时刻只能一个线程访问,保证线程是同步的。

  1. 使用同步代码块

    1. 使用关键字 syncronized 修改共享代码块
    2. 同步:代码一行一行的往下执行
    3. 异步:多个线程同时执行
    4. 锁对象:任意的对象类型 ,只有线程拿到此对象,才能执行代码。

    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();
    }
posted @ 2017-10-28 17:07  yinder  阅读(336)  评论(0编辑  收藏  举报