【java基础】多线程编程

1、线程与进程

程序是一段静态代码。
进程是程序的一次动态执行过程(代码加载,执行之执行完毕)。
线程是比进程更小的执行单元,一个进程执行过程中可以产生多个线程。

2、线程的生命周期

新建 使用Thread类及其子类表示线程。
运行 调用start()方法通知JVM,run()方法执行。如果线程是Thread的子类创建的,需要重写run()方法,run()方法没有结束之前不能再让线程执行start方法,否则会产生异常(ILLegalThreadStateException)。
中断 线程切换,
执行了sleep()方法进入休眠状态,
执行了wait()方法进入等待状态,
执行某操作,进入阻塞状态。
死亡 线程完成了全部工作,结束了run()方法,
强制性终止。

3、Thread类

创建线程

通常使用的构造方法Thread(Runnable target)。参数是Runnable类型的接口。

常用方法

start() 启动线程,线程就绪。
run() 执行,完成实际操作。
sleep(int ) 休眠,暂停一段时间。
isalive() 新建状态时为false,run状态(死亡之前)时为true
currentThread() 返回当前线程
interrupt() 唤醒休眠线程重新排队,interruptException异常抛出

4、Java的多线程机制

Java一大特点:支持多线程。多线程是指一个应用程序中同时存在几个执行体,线程的中断与恢复可以更加节省系统的开销。
每一个Java应用程序都有一个默认的主线程。比如main方法(主线程),如果主线程中再创建线程,即成为其他线程。

多线程的实现

(1)继承Thread类,重写run()方法

class testthread extends Thread{
	public void run(){
		system.out.println("hello");
	}
}

(2)实现Runnable接口,并实现接口的run()方法

public class WorkThread implements Runnable {
    @Override
    public void run() {
        System.out.println("start work thread");
    }
}

执行线程的方法:

WorkThread workThread = new WorkThread();
//方法一
Thread thread = new Thread(workThread);
thread.start();
//方法二:使用线程池
ExecutorService executorService=Executors.newSingleThreadExecutor();
executorService.execute(workThread);

(3)实现Callable接口,重写call()方法
推荐使用(2)

5、线程同步

多个线程同时访问或(某一个线程要)修改一个变量。
需要使用synchronized修饰的方法,当一个线程A使用这个方法,其他线程想使用需等待A完成。同步机制保证资源的安全,而异步能提高程序的效率。
想实现同步操作,必须获得每一个线程对象的锁。

实现的方法:

(1)用synchronized修饰方法或某一块代码。
(2)wait()中断方法执行,使本线程等待,允许其他线程使用同步方法。
notifyAll()通知所有处于等待的线程结束等待。
notify() 通知某一线程结束等待。
(3)Lock接口及实现类ReentrantLock,
方法:lock()获取锁、tryLock()、lockInterrupttibly()
不要同时使用(1)与(3)

线程管理

线程睡眠 sleep
线程让步
yield 让出CPU资源给其他线程
线程合并join方法
主线程执行完run方法后,再执行join后面的代码。
终止线程
stop方法与suspend方法,但它们不安全。
一般建议让线程自动结束。
守护线程与用户线程
执行一些后台作业,播放音乐,加载或保存参数之类。
setDaemon(true);
设置线程优先级

线程安全

共享资源避开存取,安排时间调度。

6、线程池Executors

创建线程池:

ExecutorService executorService = Executors.newCachedThreadPool();//可缓存线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);//定长线程池,
ExecutorService executorService = Executors.newSingleThreadExecutor();//一个单线程化的线程池
ExecutorService executorService = Executors.newScheduledThreadPool(5);//时间间隔周期性执行一个任务。

ExecutorService的执行方法:

.execute(Runnable)
.submit(Runnable)
.invokeAny(..)
.invokeAll(..)

上面两个队高负载的应用不友好。
内部调用ThreadPoolExecutor创建线程池。

new ThreadPoolExecutor( int corePoolSize, //核心线程池大小
           int maximumPoolSize, // 线程池最大值
           long KeepAliveTime,  // 空闲线程保留时间
           TimeUnit unit,       // 保留时间单位
           BlockingQueue<Runnable> workQueue,  // 阻塞队列任务
           RejectedExecutionHandler handler);  // 拒绝处理机制
线程池的执行流程

任务进入,首先判断核心线程是否是空闲状态,
如果不是,执行任务;
如果核心线程数已满,判断任务队列是否有空间存放任务;
如果有,保存进任务队列,等待执行;
如果满了,判断最大可容纳的线程数;
如果没有超过,开创非核心线程执行任务;
超出的话,调用handler实现拒绝策略。

ScheduleThreadPoolExecutor
时间间隔周期性执行一个任务。

ScheduledExecutorService schedulepool=Executors.newScheduledThreadPool
schedulepool.schedule(thread,10,TimeUnit.Seconds)

锁lock
死锁:两个线程等待对方执行完继续执行避免死锁,

ThreadLocal

并发编程的时候,成员变量如果不做任何处理,是线程不安全的。
ThreadLocal是线程Thread类中属性threadLocals的管理者
它的get、set、remove操作其实是对于当前线程Thread实例的threadLocals进行存取删除操作。

与synchronized区别

使用synchronized表示当前只有一个线程访问该属性,代码块或方法,其他线程被阻塞。
使用ThreadLocal则是表示每一个线程的本地变量的副本。

遵循原则:

(1) 将之声明为private static final
(2)使用之后调用remove方法移除

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值