目录
文章目录
一、线程的声明周期
二、线程的同步
一、synchronized同步的方法:(synchronized 关键字用于保护共享数据---->表示外面的线程不能进来)
二、通过Objectwait与notify
三丶线程的通信
四丶线程池
1.为什么使用线程池?
2、线程池的核心参数
3丶线程池执行任务的流程
4丶线程池的使用
总结
提示:以下是本篇文章正文内容,下面案例可供参考
示例:
1、synchronized同步方法
即有synchronized关键字修饰的方法。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类。
2、synchronized同步代码块
即有synchronized关键字修饰的语句块。 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步
package com.xhj.thread;
/**
* 线程同步的运用
* @author XIEHEJUN
*/
public class SynchronizedThread {
class Bank {
private int account = 100;
public int getAccount() {
return account;
}
/**
* 用同步方法实现
*
* @param money
*/
public synchronized void save(int money) {
account += money;
}
/**
* 用同步代码块实现
*
* @param money
*/
public void save1(int money) {
synchronized (this) {
account += money;
}
}
}
class NewThread implements Runnable {
private Bank bank;
public NewThread(Bank bank) {
this.bank = bank;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
// bank.save1(10);
bank.save(10);
System.out.println(i + "账户余额为:" + bank.getAccount());
}
}
}
/**
* 建立线程,调用内部类
*/
public void useThread() {
Bank bank = new Bank();
NewThread new_thread = new NewThread(bank);
System.out.println("线程1");
Thread thread1 = new Thread(new_thread);
thread1.start();
System.out.println("线程2");
Thread thread2 = new Thread(new_thread);
thread2.start();
}
public static void main(String[] args) {
SynchronizedThread st = new SynchronizedThread();
st.useThread();
}
}
同步块:同步块是通过锁定一个指定的对象,来对同步块中包含的代码进行同步----->同步块中包括的是线程操作的操作方法 不能多包括也不能少包括
当一个线程进入wait时,只能等另一个线程进入notify去释放他 从而可以达到有序进行 如果是多个的话就是去竞争 所以必须声明在synchronized里面 因为只能有一个线程去释放wait
不过lock和unlock就不一样了 他们俩 是线程直接进去然后锁住 然后自己出来解锁 依然可以和另一个线程去竞争再吃进入run方法里面 并且lock和unlock方法必须声明在try{}finally{}方法里面 不过lock里面可以把参数声明为(true)从而使其有序的进行
实现多个线程互斥访问临界区资源,Object类这几个方法必须配合synchronized来进行使用。
wait():使一个线程处于等待状态,并且释放所持有的对象的lock。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
notifyaAl():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。
sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
线程的通信其中一种就是交替打印 用wait 和 notify方法可以实现
该处使用的url网络请求的数据。
线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。
使用线程池的好处:
降低资源消耗。 通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
提高响应速度。 当任务到达时,任务可以不需要的等到线程创建就能立即执行。
提高线程的可管理性。 线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
corePoolSize : 核心线程大小。线程池一直运行,核心线程就不会停止。
maximumPoolSize :线程池最大线程数量。非核心线程数量=maximumPoolSize-corePoolSize
keepAliveTime :非核心线程的心跳时间。如果非核心线程在keepAliveTime内没有运行任务,非核心线程会消亡。
workQueue :阻塞队列。ArrayBlockingQueue,LinkedBlockingQueue等,用来存放线程任务。
defaultHandler :饱和策略。ThreadPoolExecutor类中一共有4种饱和策略。通过实现RejectedExecutionHandler接口。
AbortPolicy : 线程任务丢弃报错。默认饱和策略。
DiscardPolicy : 线程任务直接丢弃不报错。
DiscardOldestPolicy : 将workQueue队首任务丢弃,将最新线程任务重新加入队列执行。
CallerRunsPolicy :线程池之外的线程直接调用run方法执行。
class NumberThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i%2==0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
class NumberThread1 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i%2!=0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
public class ThreadPool {
public static void main(String[] args) {
//1.提供指定数量的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//设置线程池的属性
//2.执行指定的线程的操作。需要提供实现Runnable接口或者Callable接口实现类的对象
service.execute(new NumberThread());//适合使用于Runnable
service.execute(new NumberThread1());//适合使用于Runnable
// service.submit();//适合使用于Callable
//关闭线程池
service.shutdown();
}
}
运行结果:
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了线程的周期 ,线程的同步,线程的通信和线程池的初步了解