java笔记8多线程

1、采用继承Thread类创建线程
定义一个java.lang.Thread类的子类,并重写其run方法:
class MyThread extends Thread{
      public void run() { ……}
}
然后生成该类的对象:MyThread myThread = new MyThread(…);
2、通过实现Runnable接口创建线程
定义实现Runnable接口的线程类
class MyThread implements Runnable{
       public void run() {……}
}
然后再利用Thread类构造线程类:
        Thread myThread = new Thread (target);
Runnable中只有一个方法:public void run(); 用以定义线程运行体;
线程的启动:myThread.start();

  1. 3、Thread类的构造方法:
    Thread ()
    Thread (Runnable target)
    Thread (Runnable target, String name)
    Thread (String name)
    Thread (ThreadGroup group, Runnable target)
    Thread (ThreadGroup group, Runnable target, String name)
    Thread (ThreadGroup group, String name)
    group — 指明该线程所属的线程组;
    target — 提供线程体的对象,必须实现Runnable接口的run()方法;
    name — 线程名称,每个线程都有自己的名字,若没有指定,则Java自动给线程赋予惟一的名字;

两种方式的比较:
使用Runnable接口
可以将CPU,代码和数据分开,形成清晰的模型;
还可以从其他类继承;
保持程序风格的一致性;
在实现Runnable接口的类中可以使用静态方法如:Thread.currentThread()获取当前线程进行控制;
直接继承Thread类
不能再从其他类继承;
编写简单,可以直接操纵线程;

  1. 4、线程的优先级
    线程的优先级用数字表示,范围从1到10,数字越大级别越高,一个线程的缺省优先级是5;
    Thread类中定义的静态成员变量:
    Thread.MIN_PRIORITY = 1
    Thread.MAX_PRIORITY = 10
    Thread.NORM_PRIORITY = 5
    新建线程将继承其父线程的优先级。一般情况下,主线程(main)具有普通优先级;
    获得和设置线程对象优先级的方法:
    int getPriority ();
    void setPriority (int newPriority);

  1. 5、线程的状态和控制
    创建状态
    new运算符创建线程对象;
    就绪状态
    调用线程的start()方法启动线程,使线程处于就绪状态,此时线程可能还并未真正执行;
    运行状态:
    JVM的线程调度管理器选中处于就绪状态的线程,使其占有CPU开始运行run()方法中的代码,直至被终止或阻塞;
    阻塞状态:该状态的线程不可运行,直至阻塞原因削除,线程转入就绪状态,重新进入线程队列排队,再次运行从终止处继续执行;
    调用了sleep()方法;
    调用了suspend()方法;
    为等候一个条件变量,线程调用wait()方法;
    输入/输出流中发生线程阻塞;

针对上述四种情况,使线程返回就绪状态的方法:
sleep()方法中的参数为休息时间,单位为毫秒,时间过去后,线程即为就绪的。
一个线程调用suspend()方法后,只能有其它线程调用它的resume()方法恢复。
如果一个线程等待条件变量,如果要停止等待,需要条件变量所在的对象调用notify()或者notifyAll()方法。
特定的I/O指令结束阻塞状态。

终止状态:有两种情况可导致线程终止
自然撤销,正常运行的线程完成了其全部工作;
调用stop()方法强制终止;
Thread提供了方法isAlive(),如果线程已经启动,但是未终止,返回true,反之,返回 false,表示该线程未启动,或者已终止。
如果isAlive()方法返回true,不能区分是就绪状态、阻塞状态还是运行状态。
注意事项:
对于任何状态,如果调用的方法和状态不符,都会引起非法状态处理异常。比如。线程刚创建后,只能调用 start ()或者 stop ()方法,如果调用其它方法就会引起非法状态处理。

image

sleep方法
可以调用Thread的静态方法:
    public static void sleep(long mills) throws InterruptedException
示例:TestInterrupt.java
join方法
合并某个线程,是一种相对原始的线程间通信形式;
例如:在threadX中执行如下代码:
try{   threadY.join(); } catch ( InterruptedException e){…}
threadX将阻塞,一直等待threadY的消亡;
示例:TestJoin.java
yield方法:主动让出CPU,给同等级或更高级线程执行的机会;
不能滥用yield(),执行线程间的上下文切换可能导致过量的系统开销;1秒钟内不能超过5次;
示例:TestYield.java

守护线程(Daemon线程)
具有最低的优先级,用于在后台为系统中的其他对象和线程提供服务;一般应该是一个独立的线程,它的run()方法是一个无限循环.
将一个用户线程设置为守护线程的方式是在线程对象启动之前调用线程对象的setDaemon(boolean on)方法。
可以利用isDaemon()方法来判断一个线程是否为守护线程;
守护线程守护线程与其它线程的区别是,如果守护线程是唯一运行着的线程,程序会自动退出
典型的守护线程例子是JVM中的系统资源自动回收线程,它始终在低级别的状态中运行,用于实时监控和管理系统中的可回收资源。

  1. 6、Java的线程同步机制:
    共享数据的线程互斥锁定
    任何时刻只允许一个线程对共享数据对象进行操作
    传送数据的线程同步机制
    对于需要传送数据的多个线程必须同步运行,步调一致,保证传送的数据及时准确收到;
    每个对象都对应于一个可称为“互斥锁”的标记,该标记保证任一时刻,只能有一个线程访问该对象;
    关键字synchronized用来表示互斥锁。当某个对象由synchronized修饰时,表明该对象在任一时刻只能由一个线程访问;

实现同步的方法例子没做
通过线程监视器,使用一个共享的条件变量,对线程同步进行更精准的控制
利用wait()、notify()、notifyAll()方法,来保证生产者与消费者的同步:生产一个,消费一个;
多线程同步机制总结:
对于多个线程共享的对象或方法,使用synchronized修饰;
若一个线程必须等待某个对象的状态改变的话,通过进入同步方法或调用wait()方法实现;
每当一个方法修改共享对象的状态时,应调用nofity()或notifyAll()进行通知;

死锁问题
线程能够被阻塞,当支持其运行所需的资源被另外一个阻塞线程锁定时,将会形成所谓的死锁(Deadlock);

Java语言自身没有提供能预防死锁的机制
死锁可能潜伏在运行的程序中,防止死锁是设计阶段的一个重要任务;
哲学家吃饭问题;死锁示例:TestDeadLock.java
解决死锁问题的方法:给条件变量施加排序;

1. 线程间的通信可以用管道流.

创建管道流:
PipedInputStream pis = new  PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
或:
PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis = new PipedInputStream(pos);

1. 用过滤流包装管道流进行读写

PrintStream p = new PrintStream( pos );
p.println(“hello”);
DataInputStream d = new DataInputStream(pis);
d.readLine();
2. 通过一个中间类来传递信息.

管道流可以连接两个线程间的通信
下面的例子里有两个线程在运行,一个往外输出信息,一个读入信息.
将一个写线程的输出通过管道流定义为读线程的输入.
outStream = new PipedOutputStream();
inStream = new  PipedInputStream(outStream);
new Writer( outStream ).start();
new Reader( inStream ).start();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值