Java线程总结

来源:互联网 发布:淘宝三星手机官网 编辑:程序博客网 时间:2024/06/08 08:18

一、线程的创建

1、继承Thread类,重写run方法

优点:简单。缺点、;已经继承Thread类,不能再继承其他的类,不能共享实例变量。

2、实现Runnable接口,重写run方法。这种情况,多个线程可以共享Runnable实例变量。

3、使用Callable和Future创建线程,实现Callable接口。

第一步:

重写call方法,作为线程执行体,有返回值。

第二步:

创建Callable实例。

第三步:

创建FureTask实例,包装Callable对象,并封装Callable对象call方法的返回值。FutureTask实现Future接口,可以通过get方法获取call方法的返回值,调用改方法,导致程序阻塞,必须等到子线程结束才可以拿到返回值。isDone方法,如果Callable已经完成,返回true。可以使用ExecutorService。submit方法传入Callable实例,返回一个Future对象。

二、控制线程

1、join

在A线程的执行过程中,调用B线程的join方法,A线程将被阻塞,直到B线程执行完成。

2、线程让步yield

将线程转到就绪状态,让线程调度器重新调度一次(可能有重新转入的运行状态)

3、线程睡眠 sleep

调用该方法的线程进入阻塞状态,是调度器可以切换到其他线程。

三、线程池

1、调用Executors工具类产生线程池,一般有三种类型的线程池。

CachedThreadPool:创建一个具有缓存功能,创建于所需数量相同的线程,在回收旧线程时停止创建新线程。

FixedThreadPool:一次性分配固定数量的线程。

SingleThreadExecutor,创建只有一个线程的线程池,如果有多个人防,按提交顺序执行。

2、ExecutorService:调用submit方法,将Runnable或者Callable对象提交到线程池,返回null或者Future对象。调用shutdown方法,线程池不在接受新的任务,原来的任务仍然执行。调用shutdownNow方法,会停止所有正在执行的任务。

四、wait和notify

wait:导致当前线程等待,知道其他线程调用该同步监视器的notify或者notifyAll方法来唤醒改线程。一般有两种形式,无参数的wait和带时间参数的的wait,后者是等待一定时间后,调用wait方法的当前线程会释放对同步监视器的锁定。
notify:唤醒同步监视器等待的一个线程。
notifyAll:唤醒在同步监视器等待的所有线程。
以上方法使用的场景:
1、对于synchronized修饰的同步方法,该类的默认实例(this)就是同步监视器,可以在同步方法里面调用这三个方法
2、对于synchronized修饰的代码块,同步监视器是synchronized后面的对象,所以必须调用该对象的三个方法。
任务达到一定数量,让线程等待:
 /**     * 使用同步代码块     *     * @param task     */    private void addTaskToService(Task task) {        synchronized (mObject) {            if (mTaskService == null) {                return;            }            while (mTaskService.getWaitingCount() >= QUEUE_LIMIT) {                try {                    Log.i(TAG, "addTaskToService: wait  " + task.getId());                    mObject.wait();                } catch (InterruptedException ex) {                }            }            Log.i(TAG, "addTaskToService Id: " + task.getId());            mTaskService.addTask(task);        }    }
任务完成,通知添加任务的线程:
synchronized (mObject) {                mObject.notifyAll();                Log.i(TAG, "onTaskDone notifyAll: " + task.getId());            }



五、Condition控制线程通信

对象使用Lock保证同步时,Java提供了一个Condition类保持协调。Condition实例绑定在一个Lock实例,调用Lock对象的newCondition方法可以得到Condition实例


await:导致当前线程等待,直到其他线程调用该Condition的signal和signalAll方法来唤醒改线程。
signal:唤醒在此Lock对象上等待的单个线程。
signalAll:唤醒在此Lock对象上等待的所有线程。
任务达到一定数量,让线程等待:
/**     * 使用对象锁     *     * @param task     */    private void addTaskToService2(Task task) {        mLock.lock();        if (mTaskService == null) {            return;        }        try {            while (mTaskService.getWaitingCount() >= QUEUE_LIMIT) {                Log.i(TAG, "addTaskToService: wait  " + task.getId());                mCondition.await();            }            Log.i(TAG, "addTaskToService Id: " + task.getId());            mTaskService.addTask(task);        } catch (InterruptedException e) {        } finally {            mLock.unlock();        }    }

任务完成,通知线程继续往里面添加:
 mLock.lock();            mCondition.signalAll();            Log.i(TAG, "onTaskDone signal(): " + task.getId());            mLock.unlock();



六、阻塞队列控制线程通信

BlockingQueue接口用来做为线程同步的工具,当向BlockingQueue添加任务,如果该队列已满,则线程被阻塞。当从BlockingQueue取出任务时,如果队列已空,则线程被阻塞。

常用的两种ArrayBlockingQueue,和LinkedBlockingQueue,可以用来控制线程池,任务的分发往队列里面添加任务使用:put,当任务完成时,使用remove。

新建一个阻塞队列,限制任务数为5:

private BlockingQueue<Task> mBlockingQueue = new ArrayBlockingQueue(5);
BlockingQueue里面添加任务:

 /**     * 使用阻塞队列     *     * @param task     */    private void addTaskToBlock(Task task) {        if (mTaskService == null) {            return;        }        try {            mBlockingQueue.put(task);            Log.i(TAG, "mBlockingQueue  " + task.getId());        } catch (InterruptedException e) {            e.printStackTrace();        }        Log.i(TAG, "addTaskToService Id: " + task.getId());        mTaskService.addTask(task);    }
任务完成,BlockingQueue取出:

 try {                mBlockingQueue.take();            } catch (InterruptedException e) {                e.printStackTrace();            }


0 0
原创粉丝点击