多线程

线程的组成:

任何线程都具有基本的组成部分:

  • cpu时间片:

操作系统(OS)会为每个线程分配时间。

  • 运行数据:

堆空间:存储线程需要使用的对象,多个线程可以共享堆中的对象。
栈空间:存储线程需要使用的局部变量,每个线程都有独立的栈。

  • 线程的逻辑代码。
创建线程(1)
  • 创建线程的第一种方式:
 - import org.junit.Test;
public class test1 {
    @Test
    public static void main(String[] args) {
        MyThread myThread=new MyThread();       //创建子类对象
        myThread.start() ;     //开启start方法
    }
}
class MyThread extends Thread {//1继承Thread类
    //覆盖run方法
    public void run() {
        for (int i = 1; i <= 50; i++) {
            System.out.println("MyThread:" + i);
        }
    }
}
  • 创建线程(2)
    创建线程的第二种方法:
 public class test2 {
    @Test
    public static void main(String[] args) {
        MyRunnable myRunnable=new MyRunnable();//  3  创建实现类对象
        Thread thread=new Thread(myRunnable);//  4  创建线程对象
        thread.start();//调用start方法
    }
}
class MyRunnable implements Runnable {//1 实现Runnable接口
    //2 覆盖run方法
    @Override
    public void run() {
        for (int i = 1; i <= 50; i++) {
            System.out.println("MyRunnable:" + i);
        }
    }
}
线程的状态(基本)
常见方法:
休眠:
public static void sleep(long millis) 

当前线程主动休眠milllis秒。

放弃:
public static void yield()

当前线程主动放弃时间片,回到就绪状态,竞争下一次时间片。

结合:
public final void join()

允许其他线程加到当前线程中。

线程的状态(等待)
线程安全问题:
需求:

A线程将“Hello”存入数组的第一个空位,B线程将“World” 存入数组的第一个空位

线程不安全:

当多个线程并发访问临界资源时,如果破坏原子操作,可能会造成数据不一致。

临界资源:

共享资源(同一对象),一次仅允许一个线程使用,才可保证其正确性。

原子操作:

不可分割的多步操作,被视作一个整体其顺序和步骤不可打乱或缺省。

线程安全:
同步方式(1)
同步代码块:

sychronized(临界资源对象){//对临界资源对象加锁
//代码(原子操作)
}

注:每个对象都有一个互斥锁标记,用来分配给线程的。

只有拥有对象互斥锁标记的线程才能,才能进入该对象加锁的同步代码块。
线程退出同步代码块时,才会释放对应的互斥锁标记。

线程的状态(阻塞)
同步方式(2)
同步方法:

synchronized 返回值类型 方法名称(形参列表 0){//当前对象(this)加锁
//代码 原子操作
}

注:只有拥有对象互斥所标记的线程,才能进入该对象加锁的同步方法当中。

线程退出同步方法时,会释放相应的互斥锁标记。

同步规则:
注意:

只有在调用包含同步代码块的方法,或者同步方法时,才需要对象的锁标记。
如果调用不包含同步代码块的方法,或普通方法时,则不需要锁标记,可直接调用。、

已知JDK中线程安全的类:

StringBuffer
Vector
HashTable

以上类的公开方法,均为synchronized修饰的同步方法

经典问题:
1. 死锁:

-List item当一个线程拥有A对象锁标记,并等待B对象锁标记,同时第二个线程拥有B对象锁标记,并等待A对象锁标记时,产生死锁。
一个线程可使用拥有多个对象锁的标记,当线程阻塞时,不会释放

2.生产者,消费者

若干个生产者在生产这些产品,这些产品将提供给若干个消费者去消费,为了是消费者和生产者能够并发执行,两者之间设置一个能够存储多个产品的缓冲区,生产者将生产的产品放入缓冲区中,消费者从缓冲区中取走产品进行消费,显然生产者和消费者之间必须保持同步,既不允许消费者从一个空的缓冲区中取走产品,也不允许生产者向一个满的缓冲区中放产品。

线程通讯
等待
  • public final void wait() -
  • public final void wait(long timeout)
  • 必须在对obj加锁的同步代码块中。在一个线程中,调用obj.wait()时,此线程会释放其拥有的所有锁标记。同时,此线程阻塞在o的等待队列中。释放锁,进入等待队列。
通知
  • public final void notify()
  • public final void notifyAll()
  • 必须在对obj’加锁的同步代码块中。从obj的Waiting中释放一个或者释放全部线程。对自身没有任何影响。

小结

线程的创建
  • 方法1:继承Thread类
  • 方法2:实现Runnable接口(一个任务Task),传入Thread对象并执行
线程安全
  • 同步代码块:为方法中的局部代码(原子操作)加锁
  • 同步方法:为方法中的所有代码(原子操作)加锁
线程间的通信
  • wait()/wait(long timeout):等待
  • notify()/notifyAll():通知

高级多线程

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值