JAVA与多线程开发(线程基础、继承Thread类来定义自己的线程、实现Runnable接口来解决单继承局限性、控制多线程程并发)

实现线程并发有两种方式:1)继承Thread类;2)实现Runnable接口。

  • 线程基础

1)程序、进程、线程;并行、并发。

2)线程生命周期:创建状态(new一个线程对象)、就绪状态(调用该对象的start()方法)、执行状态(run()方法体的执行)、阻塞状态(sleep()/wait()方法的调用)、终止状态(destroy()/stop()非正常结束、或、run()方法体跑完后正常结束)。         另外从阻塞状态到执行状态,可用方法notify()/notifyAll()。

  • 定义自己的线程——继承Thread类

在Java里实现多线程,只需要我们继承Thread类,并且覆写run()方法来执行我们想要的逻辑代码即可,仅此而已!

public class MyThread extends Thread{...public void run(){...}...}     Thread t=new MyThread(i);//创建状态     t.start();//就绪状态,start()方法会自动触发t对象的run()方法体的执行,从而进入执行状态;但是,至于什么时候执行、线程之间的执行顺序都是不可预测的了,完全有OS决定

  • 解决继承局限性(单继承)——实现Runnable接口

1)通过继承Thread类,可以实现多线程并发;但是由于Java的单继承,使得MyThread类不能再继承其他的父类。

2)可以通过实现Runnable接口的方法,这样不仅能够满足多线程并发,还能满足继承其它父类。

class Parent{...}     public class MyThread extends Parent implements Runnable{...public void run(){...}...}  Thread t=new Thread(new MyThread(i));//先实例化自定义类MyThread的对象,再通过该对象作为参数实例化Thread对象     t.start();//进而调用Thread对象的start()方法

  • 控制多线程并发

1)sleep()方法——让线程休眠

try{ sleep(2000); }catch(InterruptedException e){...}//sleep()方法会抛出异常,所以要catch处理。

注意:sleep()方法在线程阻塞的过程中,并不释放自己已经占用的资源;所以说,sleep()虽然可以提高CPU资源利用率,但是也会增加发生死锁的可能性

2)通过synchronized关键字声明同步,实现对临界资源的互斥访问

  2.1)对访问互斥资源的方法添加synchronized关键字,实现互斥访问————synchronized方法

    class SynObj{  public synchronized void synAdd(){a--...i++...}     public synchronized void synMinus(){...i--...b++}  }//每当线程调用用synchronized修饰的同步方法时,就获得了当前对象SynObj的锁资源,此时其他线程就不能再调用这个对象SynObj的同步方法了

  2.2)对访问互斥资源的方法添加synchronized关键字的缺陷是,a--,b++这些非互斥的资源也不能访问了。所以Java还提供了更好的方法————synchronized块

    class SynObj{  Object o=new Object();  public void synAdd(){a--... synchronized(o){i++}...}     public void synMinus(){...synchronized(o){i--}...b++}  }//synchronized块通过指定一个无意义的新对象作为同步的令牌,而不是使用当前对象SynObj本身,这就保证了不用在方法的整个过程锁住SynObj对象,而只要在真正访问互斥资源的逻辑代码段锁住对象即可。

3)sleep()、wait()、notify()、notifyAll()

sleep():来自Thread类。sleep()方法在线程阻塞的过程中,并不释放自己已经占用的资源

wait():来自Java类的父类Object类,由notify()唤醒。wait()方法在线程阻塞的过程中,会释放自己已经占用的资源

notify():随机从因为wait()方法而被阻塞的多个线程中选择一个唤醒,至于选择哪一个是无法预测的

notifyAll():

4)产生死锁的原因:多个进程竞争临界资源;进程推进顺序不当。

5)Java把线程分为10个优先级別,分别用1-10表示;数字越小优先级别越高,表示该线程运行的逻辑越紧要,系统会分配更多的CPU时间给高优先级线程(注意,不是一定先运行)。通过setPriority(i)、getPriority()来对优先级进行存取。

上一篇:PHP+百度地图API+JAVASCRIPT实现GPS坐标与百度坐标转换的实例


下一篇:ASP.NET Core 中文文档 第三章 原理(2)中间件