java 多线程学习笔记

来源:互联网 发布:天翼进销存软件汽配 编辑:程序博客网 时间:2024/06/14 07:46

一、java多线程实现方式
1. 继承Thread类
public class MyThread extends Thread{
@Override
public void run() {
//methods
}
}
MyThread myThread = new MyThread();
myThread.start();
2. 实现Runnable接口
public class ThreadObject implements Runnable{
@Override
public void run() {
//methods
}
}
ThreadObject threadObject = new ThreadObject();
Thread myThread = new Thread(threadObject);
myThread.start();
3. 两种方法的比较
(1) 继承Thread类的方式比实现Runnable接口的方式编程更加简单,但是在继承Thread类后则不能继承其他类,而实现Runnable接口的情况下还可以继承其他类。
(2) 实现Runnable接口的方式编程稍微复杂一点,但是它是通过传入对象进行线程的构建和启动,方便实现多线程的资源共享。
(3) 继承Thread类可以直接通过this访问当前线程对象,而实现Runnable接口则需要通过Thread.currentThread()获取正在运行的线程对象。
二、线程生命周期
这里写图片描述
三、 线程的常用API
1. currentThread
返回代码段正在被哪个线程调用的信息Thread.currentThread()。
2. isAlive
判断线程是否处于活动状态。
3. sleep
在指定毫秒数内让正在执行的线程暂停执行,进入阻塞状态,且线程占有的资源和同步锁不会被释放。
4. getId
获取线程的唯一标识
5. interrupt
停止线程,为当前线程打上停止标记,并不是真正的break线程,程序可以根据此标记来选择停止还是继续运行线程。this.interrupted()和this.isInterrupt均可判断当前线程是否打上中断标记。区别在于this.interrupt调用后会清除中断标记。
6.yield
使当前线程放弃CPU资源,将它让给其他任务去占用。
7.setPriority
设置线程优先级。
四、线程同步
当多个线程同时访问统一资源时,容易造成资源的混乱,线程不安全,线程同步即解决资源的并发访问问题。
1. synchronized同步方法
(1)对其他synchronized同步方法或者同步代码块调用呈阻塞状态。
(2)同一时间只能有一个线程能够调用synchronized方法中的代码,对象监视器为该方法所在类的实例化对象。
2. synchronized(this)同步代码块
(1)对其他synchronized同步方法或者同步代码块调用呈阻塞状态。
(2)同一时间只能有一个线程能够调用synchronized(this)内部的代码块,对象监视器为该方法所在类的实例化对象。
3.synchronized(非this的任意对象)
(1)当多个线程持有的对象监视器为同一个对象时,同一时间只有一个线程能够执行synchronized(非this的任意对象)内部的代码块。
(2)对其他持有相同的对象监视器的同步代码块调用呈阻塞状态。
4. volatile关键字
线程在运行时一般条件下是直接从私有数据栈取得数据,对私有数据栈进行操作后再将数据同步到公共堆栈中。这会造成私有堆栈中的值与公共内存堆栈中的值不同步,各个线程的值不同步,不可见。volatile的作用是强制从公共堆栈中取值,增加实例变量在在多个线程中的可见性。
synchronized也具有将线程私有数据栈与公共数据栈同步的功能。
volatile只是能够进行数据的同步,即保证取到的值是公共数据栈最新的值,并不能控制线程对资源的同步访问。
5. Lock的使用
(1) ReentrantLock
ReentrantLock与synchronized一样有同步的功能,而且使用更加灵活,具有嗅探锁定、多路分支等功能。
private ReentrantLock lock = new ReentrantLock ();
lock.lock();
//需要同步的代码块
lock.unlock();
(2) 使用Condition实现等待、通知
private ReentrantLock lock = new ReentrantLock ();
private Condition = lock.newCondition();
lock.lock();
condition.await();//进入等待状态,知道收到signal消息或者外部中断
lock.unlock();

lock.lock();
condition.signal();//唤醒相同conditon下等待同步锁的线程
lock.unlock();
condition的await方法类似于Object的wait方法;
condition的singal方法类似于Object的nofity方法;
condition的singalAll方法类似于Object的notifyAll方法。
condition最大的特点是可以对线程进行分组通知唤醒。
(3) 读写锁ReentrantReadWriteLock
ReentrantLock是完全排他的效果,而ReentrantReadWriteLock有两个锁,读锁和写锁,读锁和读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。同一时间可以有多个线程进行读操作,只能有一个线程进行写操作。
lock.readLock.lock(); //获得读锁
lock.readLock.unlock();//释放读锁
lock.writeLock.lock();//获得写锁
lock.writeLock.unlock;//释放写锁
四、线程间通信
1. 等待与通知(wait and notify)
(1) wait
方法wait在同步方法或者同步块中调用,在调用前一定要获得对象级别的同步锁,不然会抛出异常。wait的作用是使当前执行代码的线程进行等待,并释放同步锁,当接到通知和中断为止,wait是Object类的方法。
(2) notify
方法notify在调用前必须获取同步锁,该方法作用是通知那些等待该对象同步锁的其他线程,线程规划器选择一个线程发起notify通知并使之持有同步锁。但是,notify调用后,当前线程不会立即释放同步锁,直到该线程将当前同步方法运行完毕。
(3) notifyAll
notifyAll是通知所有等待该同步锁的线程,唤醒所有线程,挨个执行。
2. 管道通信
(1) 字节流通信
PipedInputStream和PipedOutputStream
(2) 字符流通信
PipedReader和PipedWriter
3. 方法join
主线程创建并启动子线程,子线程要进行耗时任务,则主线程会在子线程运行结束前早早结束。如果想让主线程在子线程结束后再结束,可以使用join。join内部是使用wait方法实现的,join方法具有释放锁的功能。
4. ThreadLocal
类ThreadLocal用于每个线程绑定自己的值,操作自己的私有变量,不被其他线程干扰。
五、Timer定时器
Timer类主要作用是设置计划任务,封装任务的类是TimerTask。
public class MyTask extends TimeTask{
@Override
public void run() {
//任务代码
}
}
Timer timer = new Timer();
timer.schedule(new MyTask(), new Date());

原创粉丝点击