java基础知识(线程池)

线程池;
线程池在系统启动时即创建大量的空闲线程,程序将一个Runnable对象传给线程池,线程池就会启动一条线程来执行该对象的run方法,当run方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待下一个Runnable对象的run方法
Java提供了一个Executors工厂类来产生线程池,该工厂类里包含如下几个静态工厂的方法来创建线程池。
1.newCachedThreadPool():创建一个具有缓存功能的线程池,系统根据需要创建线程,这些线程将会被缓存在线程池中。
2.newFixedThreadPool(int nThreads):创建一个可重用,具有固定线程数的线程池。
3.newSingleThreadExecutor():创建一个只有单线程的线程池,它相当于newFixedThreadPool方法时传入1.
4.newScheduledThreadPool(int corePoolSize):创建具有指定线程数的线程池,它可以在指定延迟后执行线程任务。CorePool Size指池中所保存的线程数,即使线程是空闲的也被保存在线程池内。
5.NewSingleThreadScheduledExecutor():创建只有一条线程的线程池,他可以在指定延迟后执行线程任务。
前三个方法返回一个ExecutorService对象,该对象代表一个线程池,他可以执行Runnable对象或Callable对象所代表的线程。而后两个方法返回一个ScheduledExecutorService线程池,它是ExecutorService的子类,他可以在指定延迟后执行线程任务。
ExecutorService代表尽快执行线程的线程池(只要线程池中有空闲线程立即执行线程任务),程序只要将一个Runnable对象或Callable对象(代表线程任务)提交给线程池即可,该线程池就会尽快执行任务。ExecutorService提供了如下三个方法:
Future submit(Callable task)提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。该 Future 的 get 方法在成功完成时将会返回该任务的结果。
如果想立即阻塞任务的等待,则可以使用 result = exec.submit(aCallable).get(); 形式的构造。
注:Executors 类包括了一组方法,可以转换某些其他常见的类似于闭包的对象,例如,将 PrivilegedAction 转换为 Callable 形式,这样就可以提交它们了。
参数:
task - 要提交的任务
返回:
表示任务等待完成的 Future
Future submit(Runnable task,
T result)提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功完成时将会返回给定的结果。

参数:
task - 要提交的任务
result - 返回的结果
返回:
表示任务等待完成的 Future
抛出:
RejectedExecutionException - 如果任务无法安排执行
NullPointerException - 如果该任务为 null
Future<?> submit(Runnable task)提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功 完成时将会返回 null。
参数:
task - 要提交的任务
返回:
表示任务等待完成的 Future
抛出:
RejectedExecutionException - 如果任务无法安排执行
NullPointerException - 如果该任务为 null
ScheduledExecutorService代表可在指定延迟或周期性执行线程任务的线程池,它提供了如下四个方法:
ScheduledFuture<?> schedule(Runnable command,
long delay,
TimeUnit unit)创建并执行在给定延迟后启用的一次性操作。

参数:
command - 要执行的任务
delay - 从现在开始延迟执行的时间
unit - 延迟参数的时间单位
返回:
表示挂起任务完成的 ScheduledFuture,并且其 get() 方法在完成后将返回 null
schedule
ScheduledFuture schedule(Callable callable,
long delay,
TimeUnit unit)创建并执行在给定延迟后启用的 ScheduledFuture。

参数:
callable - 要执行的功能
delay - 从现在开始延迟执行的时间
unit - 延迟参数的时间单位
返回:
可用于提取结果或取消的 ScheduledFuture
ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit)创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。如果任务的任何一个执行遇到异常,则后续执行都会被取消。否则,只能通过执行程序的取消或终止方法来终止该任务。如果此任务的任何一个执行要花费比其周期更长的时间,则将推迟后续执行,但不会同时执行。

参数:
command - 要执行的任务
initialDelay - 首次执行的延迟时间
period - 连续执行之间的周期
unit - initialDelay 和 period 参数的时间单位
返回:
表示挂起任务完成的 ScheduledFuture,并且其 get() 方法在取消后将抛出异常
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit)创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。如果任务的任一执行遇到异常,就会取消后续执行。否则,只能通过执行程序的取消或终止方法来终止该任务。

参数:
command - 要执行的任务
initialDelay - 首次执行的延迟时间
delay - 一次执行终止和下一次执行开始之间的延迟
unit - initialDelay 和 delay 参数的时间单位
返回:
表示挂起任务完成的 ScheduledFuture,并且其 get() 方法在取消后将抛出异常
当用完一个线程池后,应该调用线程池的shutdown()方法,该方法将启动线程池的关闭序列,调用了shutdown()方法后的线程池不再接受新任务,但会将以前所有已提交任务执行完成。当线程池中所有任务都执行完成后,池中所有线程都会死亡;另外也可以调用线程池的shutdownNow()方法来关闭线程池,该方法试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
使用线程池来执行线程任务的步骤如下:
1.调用Executors类的静态工厂方法创建一个ExecutorService对象,该对象代表一个线程池
2.创建Runnable实现类或Callable实现类的实例,作为线程执行任务。
3.调用ExecutorService对象的submit方法来提交Runnable实例或Callable实例
4.当不想提交任何任务时调用ExecutorService对象的shutdown方法来关闭线程池。
如:
public class TestThread1 implements Runnable {
//实现Runnable接口来定义一个简单的线程类
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+“的i值为:”+i);
}
}
}
public class ThreadPoolTest {
public static void main(String[] args) {
//创建一个具有固定线程数(6)的线程池
ExecutorService pool=Executors.newFixedThreadPool(6);
//向线程池中提交两个线程
pool.submit(new TestThread1());
pool.submit(new TestThread1());
//关闭线程池
pool.shutdown();
}
}
线程相关类:
Java还为线程安全提供了一些工具类,如:ThreadLocal类,它代表一个线程局部变量,通过把数据放在ThreadLocal中可以让每条线程创建一个该变量的副本,从而避免并发式发访问的线程安全问题。
ThreadLocal类:
ThreadLocal,是ThreadLocal variable(线程局部变量)的意思,也许将它命名为ThreadLocalVar更加合适。线程局部变量(Thread Local)的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立的改变自己的副本,而不会和其他线程的副本冲突。
ThreadLocal类的用法非常简单,它只提供了如下三个public方法:
T get():返回此线程局部变量中当前线程副本中的值。
Void remove():删除此线程的局部变量中当前线程的值
Void set(T value):设置此线程局部变量中当前线程副本中的值。
如:
public class Account {
//定义一个ThreadLocal类型的变量,该变量将是一个线程局部变量
//每个线程都会保留该变量的一个副本
private ThreadLocal name=new ThreadLocal();
//定义一个初始化name属性的构造器
public Account(String str)
{
this.name.set(str);
//输出初始名
System.out.println("------"+this.name.get());
}
public String getName() {
return name.get();
}
public void setName(String str) {
this.name.set(str);;
}

}
public class Mytest extends Thread{
//定义一个Account属性
private Account account;
public Mytest(Account account,String name)
{
super(name);
this.account=account;
}
public void run() {
for (int i = 0; i < 10; i++) {
if(i==6)
{
account.setName(getName());

		}
		System.out.println(account.getName()+"账户的i值"+i);
	}
}

}
public class ThreadLocalTest {
public static void main(String[] args) {
//启动两条线程,两条线程共享一个Account
Account at=new Account(“初始名”);
new Mytest(at, “线程甲”).start();
new Mytest(at, “线程乙”).start();
}
}
在这里插入图片描述
包装线程不安全集合:
可以使用Collections提供的静态方法来把这些集合包装成线程安全的集合。Collection提供了如下几个静态方法:
public static Collection synchronizedCollection(Collection c)返回指定 collection 支持的同步(线程安全的)collection。为了保证按顺序访问,必须通过返回的 collection 完成所有对底层实现 collection 的访问。
在返回的 collection 上进行迭代时,用户必须手工在返回的 collection 上进行同步:
Collection c = Collections.synchronizedCollection(myCollection);

synchronized© {
Iterator i = c.iterator(); // Must be in the synchronized block
while (i.hasNext())
foo(i.next());
}
不遵从此建议将导致无法确定的行为。
返回的 collection 不会 将 hashCode 和 equals 操作传递给底层实现 collection,但这依赖于 Object 的 equals 和 hashCode 方法。在底层实现 collection 是一个 set 或一个列表的情况下,有必要遵守这些操作的协定。

如果指定 collection 是可序列化的,则返回的 collection 也将是可序列化的。

参数:
c - 被“包装”在同步 collection 中的 collection。
返回:
指定 collection 的同步视图。


synchronizedSet
public static Set synchronizedSet(Set s)返回指定 set 支持的同步(线程安全的)set。为了保证按顺序访问,必须通过返回的 set 完成对所有底层实现 set 的访问。
在返回的 set 上进行迭代时,用户必须手工在返回的 set 上进行同步:

Set s = Collections.synchronizedSet(new HashSet());

synchronized(s) {
Iterator i = s.iterator(); // Must be in the synchronized block
while (i.hasNext())
foo(i.next());
}
不遵从此建议将导致无法确定的行为。
如果指定 set 是可序列化的,则返回的 set 也将是可序列化的。

参数:
s - 被“包装”在同步 set 中的 set。
返回:
指定 set 的同步视图。


synchronizedSortedSet
public static SortedSet synchronizedSortedSet(SortedSet s)返回指定有序 set 支持的同步(线程安全的)有序 set。为了保证按顺序访问,必须通过返回的有序 set(或其视图)完成对所有底层实现有序 set 的访问。
在返回的有序 set 上或者其任意 subSet、headSet 或 tailSet 视图上进行迭代时,用户必须手工在返回的有序 set 上进行同步。

SortedSet s = Collections.synchronizedSortedSet(new TreeSet());

synchronized(s) {
Iterator i = s.iterator(); // Must be in the synchronized block
while (i.hasNext())
foo(i.next());
}
或者:
SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
SortedSet s2 = s.headSet(foo);

synchronized(s) { // Note: s, not s2!!!
Iterator i = s2.iterator(); // Must be in the synchronized block
while (i.hasNext())
foo(i.next());
}
不遵从此建议将导致无法确定的行为。
如果指定的有序 set 是可序列化的,则返回的有序 set 也将是可序列化的。

参数:
s - 被“包装”在同步有序 set 中的有序 set。
返回:
指定有序 set 的同步视图。


synchronizedList
public static List synchronizedList(List list)返回指定列表支持的同步(线程安全的)列表。为了保证按顺序访问,必须通过返回的列表完成所有对底层实现列表的访问。
在返回的列表上进行迭代时,用户必须手工在返回的列表上进行同步:

List list = Collections.synchronizedList(new ArrayList());

synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
不遵从此建议将导致无法确定的行为。
如果指定列表是可序列化的,则返回的列表也将是可序列化的。

参数:
list - 被“包装”在同步列表中的列表。
返回:
指定列表的同步视图。


synchronizedMap
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)返回由指定映射支持的同步(线程安全的)映射。为了保证按顺序访问,必须通过返回的映射完成所有对底层实现映射的访问。
在返回映射的任意 collection 视图上进行迭代时,用户必须手工在返回的映射上进行同步:

Map m = Collections.synchronizedMap(new HashMap());

Set s = m.keySet(); // Needn’t be in synchronized block

synchronized(m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
不遵从此建议将导致无法确定的行为。
如果指定映射是可序列化的,则返回的映射也将是可序列化的。

参数:
m - 被“包装”在同步映射中的映射。
返回:
指定映射的同步视图。


synchronizedSortedMap
public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)返回指定有序映射支持的同步(线程安全的)有序映射。为了保证按顺序访问,必须通过返回的有序映射(或其视图)完成对所有底层有序映射的访问。
当在返回的有序映射的 collection 视图或者其任何 subMap、headMap 或 tailMap 视图进行迭代时,用户必须手工在该映射上进行同步:

SortedMap m = Collections.synchronizedSortedMap(new TreeMap());

Set s = m.keySet(); // Needn’t be in synchronized block

synchronized(m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
或者:
SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
SortedMap m2 = m.subMap(foo, bar);

Set s2 = m2.keySet(); // Needn’t be in synchronized block

synchronized(m) { // Synchronizing on m, not m2 or s2!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
不遵从此建议将导致无法确定的行为。
如果指定的有序映射是可序列化的,则返回的有序映射也将是可序列化的。

参数:
m - 被“包装”在同步有序映射中的有序映射。
返回:
指定有序映射的同步视图。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值