线程的笔记

多线程

进程和线程的概念:
   进程:程序是静止的,运行中的程序就是进程。
   进程的特点:
      动态性:进程是在运行的,会占用内存资源和CPU资源。
      独立性:进程与进程之间各自占用各自的内存资源,互相独立。
      并发性:假如计算机中只有一个CPU,CPU是单核的。那么同一个时刻,其实计算机中只能有一个进程在执行, 我们看到了很多进程在一起执行,原因是CPU会分时轮询依次 为每个进程服务,因为轮询的速度非常的块给我们的感觉 好像这些进程在同时运行,这就是进程并发!
        并行:是同一个时刻,真的在同时运行。
        线程: 一个进程可以包含多个线程。


   线程的特点:
      多态性,并发性

多线程(Thread):一个进程包含了多个线程就是多线程。
    多线程可以提高程序的运行效率,多线程可以设计一些业务模型。多线程的执行会出现随机性,原因是因为他们是并发执行的!

创建线程的步骤:
   (1)定义一个线程MyThread类继承Thread.
   (2)在线程类MyThread类中重写run方法,申明线程需要完成的任务。
   (3)创建MyThread线程类的对象代表了一个新线程
   (4)调用线程的start方法启动线程

线程的创建方式一

public class ThreadDemo01 {
    // 进程:ThreadDemo01
    // 线程1:main方法,main本身就是一个线程,称为最牛逼的主线程!
    // 线程2:t线程
    public static void main(String[] args) {
        // (3)创建MyThread线程类的对象代表了一个新线程
        MyThread t = new MyThread();
        // (4)调用线程的start方法启动线程。自动调用线程的run()方法
        t.start();
        for (int i = 0 ; i < 5 ; i++ ){
            System.out.println("main输出:"+i);
        }
    }
}
// MyThread是一个线程类,不是线程,MyThread类是用来创建线程的!
// (1)定义一个线程MyThread类继承Thread.
class MyThread extends Thread{
    // (2)在线程类MyThread类中重写run方法,申明线程需要完成的任务。
    @Override
    public void run() {
        for (int i = 0 ; i < 5 ; i++ ){
            System.out.println("线程输出:"+i);
        }
    }

}

  

线程Thread的常用API介绍。


(1)获取线程的名称 getName();

MyThread t1 = new MyThread();
t1.setName("子线程2号");
System.out.println(t1.getName());

(2)获取当前线程对象的API: Thread.currentThread();
     哪个线程中执行这个API就可以得到哪个线程对象。
     主线程的默认名称是:main
     子线程的默认名称是:Thread_索引

Thread main = Thread.currentThread();
main.setName("最牛逼的线程");

(3)setName(String name)为线程设置名字

        // 创建一个子线程 MyThread t = new MyThread();

                                        t.setName("子线程1号");

线程取名字的优化方法_构造器

MyThread t = new MyThread("子线程1号");
t.start();

构造器必须重写父类有参构造方法

class MyThread extends Thread{
    public MyThread(String name){
        // public Thread(String name)
        super(name);
    }}

线程的创建方式二

步骤:
  (1)定义一个线程任务类实现Runnable接口。
  (2)重写run()方法。
  (3)创建线程任务类对象,创建一个Thread线程对象包装线程任务对象。
  (4)启动线程对象。

public class ThreadDemo01 {
    public static void main(String[] args) {
        //(3)创建线程任务类对象,。
        RunnableTarget target = new RunnableTarget();
        // Thread(Runnable target)
        // Thread(Runnable target,String name)
        // 创建一个Thread线程对象包装线程任务对象
        Thread t = new Thread(target,"子线程1号");
        t.start();

        Thread t1 = new Thread(target,"子线程2号");
        t1.start();

        for (int i = 0 ; i < 5 ; i++ ){
            System.out.println(Thread.currentThread().getName()+"=>输出:"+i);
        }
    }
}

// (1)定义一个线程任务类实现Runnable接口。
class RunnableTarget  implements Runnable{
    // (2)重写run()方法。
    @Override
    public void run() {
        for (int i = 0 ; i < 5 ; i++ ){
            System.out.println(Thread.currentThread().getName()+"=>输出:"+i);
        }
    }
}

Runnable的匿名内部类方式创建线程!!

public class ThreadDemo02 {
    public static void main(String[] args) {

        // 线程任务对象!
        Runnable target = new Runnable() {
            @Override
            public void run() {
                for (int i = 0 ; i < 5 ; i++ ){
                    System.out.println(Thread.currentThread().getName()+"=>输出:"+i);
                }
            }
        };

        // Thread(Runnable target)
        // Thread(Runnable target,String name)
        // 创建一个Thread线程对象包装线程任务对象
        Thread t = new Thread(target,"子线程1号");
        t.start();

        Thread t1 = new Thread(target,"子线程2号");
        t1.start();

        for (int i = 0 ; i < 5 ; i++ ){
            System.out.println(Thread.currentThread().getName()+"=>输出:"+i);
        }
    }
}

创建方式二的优缺点:
    缺点:编码相对复杂,不能得到线程执行的结果。
    优点:线程任务对象只是实现了Runnable接口,可以继续继承其他类,
         可以继续实现其他接口。
         线程任务对象的本身的功能可以增强,
         非常适合做线程池。
         非常适合做共享资源的访问。

 

线程的创建方式三

步骤:
   (1)创建一个线程任务对象,实现Callable接口,申明线程执行的结果类型。
        重写call方法。
   (2)创建一个未来任务对象FutureTask对象,包装Callable实现类对象。
   (3)创建一个线程对象Thread来包装FutureTask对象
   (4)启动线程。
   (5)获取线程执行的结果。
public class ThreadDemo01 {
    public static void main(String[] args) {
        // (2)创建一个未来任务对象FutureTask对象,包装Callable实现类对象。
        CallableTarger targer = new CallableTarger();
        //  未来任务对象的功能:可以在线程执行完毕以后得到线程的执行结果。
        //  未来任务对象实际上就是一个Runnable对象
        FutureTask<String> task = new FutureTask<>(targer);
        // public Thread(Runnable task)
        // (3)创建一个线程对象Thread来包装FutureTask对象
        Thread t = new Thread(task);
        // (4)启动线程。
        t.start();

        for(int i = 1 ; i <= 5 ; i++ ){
            System.out.println(Thread.currentThread().getName()+"=>输出:"+i);
        }

        // (5)获取线程执行的结果。
        try {
            String rs = task.get();
            System.out.println(rs);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//  (1)创建一个线程任务对象,实现Callable接口,申明线程执行的结果类型。
// 需求:让线程求和,求 1-5的和返回。
class CallableTarger implements Callable<String>{
    @Override
    public String call() throws Exception {
        int sum = 0 ;
        for(int i = 1 ; i <= 5 ; i++ ){
            sum+=i;
            System.out.println(Thread.currentThread().getName()+"=>输出:"+i);
        }
        return Thread.currentThread().getName()+"求和返回:"+sum;
    }
}

                               线程安全问题及解决

什么是线程安全问题?
线程安全问题的原因:
   多个线程在操作同一个共享资源的时候,可能出现线程安全问题。

目标:模拟线程安全问题的取款案例。

 

解决方法:

线程同步:为了解决线程安全问题。
线程同步的核心思想是什么呢?
    让共享资源的访问实现先后访问。
    核心点:把出现线程安全问题的代码给锁起来,每次只能有一个线程访问
        其他线程必须等待这个线程执行完毕以后才可以进来访问。
线程同步的方式:
   (1)同步代码块

public void draw(int drawMoney) {
    String name = Thread.currentThread().getName();
    synchronized (this){
        if(money >= drawMoney){
            System.out.println(name+"来取钱,吐出"+drawMoney);
            // 更新余额
            money -= drawMoney;
            System.out.println(name+"来取钱,取款后剩余"+money);
        }else{
            System.out.println(name+"来取钱,但毛钱没有!!");
        }
    }
}

   (2)同步方法

public synchronized void draw(int drawMoney) {
    String name = Thread.currentThread().getName();
    if(money >= drawMoney){
        System.out.println(name+"来取钱,吐出"+drawMoney);
        // 更新余额
        money -= drawMoney;
        System.out.println(name+"来取钱,取款后剩余"+money);
    }else{
        System.out.println(name+"来取钱,但毛钱没有!!");
    }
}

   (3)lock锁

public  void draw(int drawMoney) {
    String name = Thread.currentThread().getName();
    lock.lock();
    try{
        if(money >= drawMoney){
            System.out.println(name+"来取钱,吐出"+drawMoney);
            // 更新余额
            money -= drawMoney;
            System.out.println(name+"来取钱,取款后剩余"+money);
        }else{
            System.out.println(name+"来取钱,但毛钱没有!!");
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        lock.unlock();
    }

}

同步代码块:
    就是把出现线程安全问题的核心代码给锁起来,每次只允许一个线程访问。
    格式:

    同步锁:原则上可以是任意唯一对象。
         按照规范:建议实例方法用this作为锁。
                 静态方法用字节码作为锁:类名.class。

 

线程控制:

线程睡眠(毫秒)

Thread类:
  public static  void sleep(long millis);
  让线程暂停一段时间

线程让步

for (int i = 0 ; i < 10 ; i++ ){
    System.out.println(main.getName()+"=>"+i);
    if(i == 3){
        // 当前线程礼让以下CPU资源
        Thread.yield();
    }
}

线程优先级
   默认优先级是:5
   级别: 1  5(默认) 10
   优先级高的线程可以更多机会得到CPU.
Thread类下:
public static final int MIN_PRIORITY = 1;  public static final int NORM_PRIORITY = 5

;public static final int MAX_PRIORITY=10;

MyThread03 t1 = new MyThread03("子线程2号");
t1.start();
t1.setPriority(Thread.MAX_PRIORITY);

让出资源

for (int i = 0 ; i < 10 ; i++ ){
    System.out.println(main.getName()+"=>"+i);
    if(i == 3){
        // 当前线程让出CPU资源,必须t1线程完全跑完再执行自己!
        try {
               //t1是线程
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public void wait()` : 让当前线程进入到等待状态 此方法必须同步锁对象调用.
public void notify()` : 唤醒当前锁对象上等待状态的一个线程  此方法必须锁对象调用.
public void notifyAll()` : 唤醒当前锁对象上等待状态的全部线程  此方法必须锁对象调用.

this  wait();     this.notify();     this.notifyAll();

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值