标签:构造方法 throw 同步 adt string 请求 依赖 维护 img
多个线程一起做同一件事情,缩短时间,提升效率
提高资源利用率
加快程序响应,提升用户体验
??
??
??
??
??通过前面的学习,可以看到,不管何种创建对象的方式,都需要新建立实例,所以我们可以通过构造函数传入参数,并将传入的数据使用类变量保存起来
??在线程类里面定义一些列的变量,然后定义set方法,在新建实例之后,调用set方法传递参数
??使用线程方法自己产生的变量值作为参数,去调取外部的方法,获取返回数据的方式
??要跨线程维护正确的可见性,只要在几个线程之间共享非 final 变量,就必须使用线程同步
??ThreadLocal利用空间换时间,通过为每个线程提供一个独立的变量副本,避免了资源等待,解决了变量并发访问的冲突问题,提高了并发量。实现了线程间的数据隔离,但是线程间无法共享同一个资源
public class StudyThread {
public static void main(String[] args) throws ExecutionException, InterruptedException {
SyncTest syncTest = new SyncTest();
ConcurrentHashMap<String, String> testConMap = new ConcurrentHashMap<>();
for (int i = 0; i < 10; i++) {
ThreadTest2 threadTest2 = new ThreadTest2();
threadTest2.setSyncTest(syncTest);
Thread threadTest = new Thread(threadTest2);
threadTest.start();
}
}
}
//实现Runnable
class ThreadTest2 implements Runnable {
private SyncTest syncTest;
public void setSyncTest(SyncTest syncTest) {
this.syncTest = syncTest;
}
@Override
public void run() {
syncTest.threadLocalTest(Thread.currentThread().getName());
}
}
class SyncTest {
private static ThreadLocal<String> threadLocal = new ThreadLocal<String>();
public void threadLocalTest(String name) {
try {
System.out.println(name + "进入了threadLocal方法!");
threadLocal.set(name);
Thread.currentThread().sleep(100);
System.out.println(threadLocal.get() + "离开了threadLocal方法!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
??不管synchronized是用来修饰方法,还是修饰代码块,其本质都是锁定某一个对象。修饰方法时,锁上的是调用这个方法的对象,即this;修饰代码块时,锁上的是括号里的那个对象
public class StudyThread {
public static void main(String[] args) throws ExecutionException, InterruptedException {
SyncTest syncTest = new SyncTest();
ConcurrentHashMap<String, String> testConMap = new ConcurrentHashMap<>();
for (int i = 0; i < 10; i++) {
ThreadTest2 threadTest2 = new ThreadTest2();
threadTest2.setSyncTest(syncTest);
threadTest2.setTestConMap(testConMap);
Thread threadTest = new Thread(threadTest2);
threadTest.start();
}
}
}
//实现Runnable
class ThreadTest2 implements Runnable {
private ConcurrentHashMap<String, String> testConMap;
private SyncTest syncTest;
public void setTestConMap(ConcurrentHashMap<String, String> testConMap) {
this.testConMap = testConMap;
}
public void setSyncTest(SyncTest syncTest) {
this.syncTest = syncTest;
}
@Override
public void run() {
//三个方法需要单独测试,因为testConMap会相互影响
//测试同步方法,锁住的对象是syncTest
//syncTest.testSyncMethod(testConMap,Thread.currentThread().getName());
//测试同步代码块,锁住的对象是testConMap
//syncTest.testSyncObject(testConMap, Thread.currentThread().getName());
//测试没有锁时执行请求是多么的混乱!!!
//syncTest.testNoneSyncObject(testConMap, Thread.currentThread().getName());
}
}
//同步测试方法类
class SyncTest {
public synchronized void testSyncMethod(ConcurrentHashMap<String, String> testConMap, String name) {
try {
System.out.println(name + "进入了同步方法!");
testConMap.put("name", name);
Thread.currentThread().sleep(10);
System.out.println(testConMap.get("name") + "离开了同步方法!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void testSyncObject(ConcurrentHashMap<String, String> testConMap, String name) {
synchronized (testConMap) {
try {
System.out.println(name + "进入了同步代码块!");
testConMap.put("name", name);
Thread.currentThread().sleep(10);
System.out.println(testConMap.get("name") + "离开了同步代码块!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void testNoneSyncObject(ConcurrentHashMap<String, String> testConMap, String name) {
try {
System.out.println(name + "进入了无人管辖区域!");
testConMap.put("name", name);
Thread.currentThread().sleep(10);
System.out.println(testConMap.get("name") + "离开了无人管辖区域!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
特点
public class StudyThread {
static int v = 1;//volatile能够保证变量的可见性
public static void main(String[] args) {
//改动线程
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
v++;//确保只有一个线程修改变量值
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//检测线程
new Thread(new Runnable() {
@Override
public void run() {
int old = 0;
while (old < 11) {
if (old != v) {
old = v;
System.out.println("检测线程:v的值变动为" + old);
}
}
}
}).start();
}
}
??Java中很多类说的线程安全指的是,它的每个方法单独调用(即原子操作)都是线程安全的,但是代码总体的互斥性并不受控制
线程安全的类有以下几类
Concurrentxxx
ThreadPoolExecutor
BlockingQueue和BlockingDeque
原子类Atomicxxx—包装类的线程安全类
CopyOnWriteArrayList和CopyOnWriteArraySet
通过synchronized 关键字给方法加上内置锁来实现线程安全:Timer,TimerTask,Vector,Stack,HashTable,StringBuffer
Collections中的synchronizedCollection(Collection c)方法可将一个集合变为线程安全:
Map m=Collections.synchronizedMap(new HashMap());
线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
public class StudyThread {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建一个线程池,该线程池重用固定数量的从共享无界队列中运行的线程
//ExecutorService threadPool = Executors.newFixedThreadPool(20);
//创建一个维护足够的线程以支持给定的并行级别的线程池,线程的实际数量可以动态增长和收缩,工作窃取池不保证执行提交的任务的顺序
//ExecutorService threadPool = Executors.newWorkStealingPool(8);
//创建一个使用从无界队列运行的单个工作线程的执行程序。
//ExecutorService threadPool = Executors.newSingleThreadExecutor();
//创建一个根据需要创建新线程的线程池,但在可用时将重新使用以前构造的线程。如果没有可用的线程,将创建一个新的线程并将其添加到该池中。未使用六十秒的线程将被终止并从缓存中删除
ExecutorService threadPool = Executors.newCachedThreadPool();
//放入Runnable类线程
for (int i = 0; i < 10; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("线程名:" + Thread.currentThread().getName());
}
});
}
//Thread.currentThread().sleep(1000);
//放入Callable类线程
List<Future<String>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Future<String> future = threadPool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("线程名:" + Thread.currentThread().getName());
return Thread.currentThread().getName();
}
});
futures.add(future);
}
threadPool.shutdown();
for (Future future : futures) {
System.out.println(future.get());
}
}
}
??
要点
public class StudyThread {
public static void main(String[] args) throws ExecutionException, InterruptedException {
int poolSize = Runtime.getRuntime().availableProcessors() * 2;
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(512);
RejectedExecutionHandler policy = new ThreadPoolExecutor.DiscardPolicy();
ExecutorService executorService = new ThreadPoolExecutor(poolSize, poolSize,
0, TimeUnit.SECONDS,
queue,
policy);
//放入Runnable类线程
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("线程名:" + Thread.currentThread().getName());
}
});
}
//放入Callable类线程
List<Future<String>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Future<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("线程名:" + Thread.currentThread().getName());
return Thread.currentThread().getName();
}
});
futures.add(future);
}
for (Future future:futures) {
System.out.println(future.get());
}
//放入Callable类线程
//使用CompletionService简化获取结果的操作,执行完一个任务,获取一个结果,结果顺序和执行顺序相同
CompletionService<String> ecs = new ExecutorCompletionService<String>(executorService);
for (int i = 0; i < 10; i++) {
Future<String> future = ecs.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("线程名:" + Thread.currentThread().getName());
return Thread.currentThread().getName();
}
});
}
for (int i = 0; i < 10; i++) {
System.out.println(ecs.take().get());
}
}
}
标签:构造方法 throw 同步 adt string 请求 依赖 维护 img
原文地址:https://www.cnblogs.com/yanghanwen/p/12337879.html