面向对象
JDK 1.5新特效性 线程并发库
传统线程回顾:
传统线程创建的俩种方式:
package com.itheima.study;
public class TraditionalThread {
public static void main(String... args) {
/*
第一个创建线程思路:
1.继承Thread类。
2.覆盖Thread类中的run方法。
3.把线程要运行的代码封装到run方法中。
4.调用strat方法,开启一个线程并调用run方法。
*/
new Thread() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName());
}
}
}.start();
/*
第二中创建线程思路:
1.实现Runnbale接口。
2.覆盖Runnable接口的run方法。
3.创建一个线程,把Runnable子类当成参数进行传递。
4.把线程要运行的代码封装到Runnable子类的run方法中。
5.调用线程的start方法,开启线程并调用run方法。
*/
new Thread(new Runnable(){
@Override
public void run(){
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}).start();
/*
如果Thread子类构造参数接收一个Runnable接口的子类对象,并且覆盖Thread子类的run方法。
那么调用strat方法会调用哪个线程里面的run方法呢?
答案:调用的是Thread子类中的run方法。
*/
new Thread(new Runnable(){
@Override
public void run(){
System.out.println("Runnable");
}
}) {
@Override
public void run(){
System.out.println("subThread");
}
}.start();
}}
}
}
/*
总结:俩种创建线程的方式,到底用哪个更合适呢?
其实俩种方法都可以,但是第二种方法更能体现面向对象的思想。
*/
定时器(定时炸弹)
package com.itheima.study;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TraditionalTimerTest {
private static int count = 0;
public static void main(String... args) {
class MyTimerTask extends TimerTask{
@Override
public void run() {
count = (count+1)%2;
System.out.println("bombing");
new Timer().schedule(new MyTimerTask(),2000+2000*count );
}
}
new Timer().schedule(new MyTimerTask() ,2000);
while(true){
System.out.println(new Date().getSeconds());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}e.printStackTrace();
}
}
}
/*
注意一点:炸弹只有一个,如果炸弹炸完了还想继续对炸弹进行操作的话,会发生异常。
(除非是连环爆破)
*/
(线程之间互斥)
package com.itheima.study;
public class TraditionalThreadSynchronized {
/*
* 静态方法中不能创建内部类的实例对象。
* 方法内的局部成员要访问外部的局部变量,那么该局部变量必须是final修饰的。
* synchroized(对象){}
* 同步函数使用的锁是this
* 静态同步函数使用的锁是该类的字节码文件
* */
public static void main(String... args) {
new TraditionalThreadSynchronized().init();
}
private void init(){
final Outputer outputer = new Outputer();
new Thread(){
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output("程序员");
}
}
}.start();
new Thread(){
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output("CSDN社区");
}
}
}.start();
}
static class Outputer{
public void output(String name){
synchronized(""){
for(int x=0;x
System.out.print(name.charAt(x));
}
System.out.println();
}
}
public synchronized void output2(String name){
for(int x=0;x
System.out.print(name.charAt(x));
}
System.out.println();
}
public static synchronized void output3(String name){
for(int x=0;x
System.out.print(name.charAt(x));
}
System.out.println();
}
}
}
总结:线程直接的互斥就是在互斥的同步代码上加锁,锁可以是任意对象,但是必须保证锁的唯一。
(线程之间的通讯)
/*
wait与notify实现线程间的通信
*/
package com.itheima.study;
public class TraditionalThreadCommunication {
public static void main(String... args) {
final ThreadStartCode threadStartCode = new ThreadStartCode();
new Thread(new Runnable(){
@Override
public void run() {
for(int x=1;x<=50;x++){
threadStartCode.sub();
}
}
}).start();
for(int x=1;x<=50;x++){
threadStartCode.main();
}
}
}
class ThreadStartCode{
private boolean falg = true;
public synchronized void sub(){
while(!falg){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int x=1;x<=10;x++){
System.out.println(Thread.currentThread().getName()+"......sub..."+x);
}
falg = false;
this.notify();
}
public synchronized void main(){
while(falg){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int x=1;x<=10;x++){
System.out.println(Thread.currentThread().getName()+"......main..."+x);
}
falg = true;
this.notify();
}
}
总结:线程之间的通讯,就是Object任意对象的wait方法和notify方法。但是有一个保证就是要先有锁对象。
(线程范围内的共享数据)
package com.itheima.study;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/*
* 问题:
* 获取线程死亡的信息。
* */
/*
* 线程范围内的共享数据
* */
public class ThreadSopeShareData {
private static Map<Thread,Integer> map = new HashMap<Thread,Integer>();
private static int data = 0;
public static void main(String... args) {
for(int x=1;x<=2;x++){
new Thread(new Runnable(){
@Override
public void run() {
int data =new Random().nextInt();
map.put(Thread.currentThread(),data);
System.out.println(Thread.currentThread().getName()+"...."+data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get(){
int data = map.get(Thread.currentThread());
System.out.println("A form "+Thread.currentThread().getName()
+"...get data :"+data);
}
}
static class B{
public void get(){
int data = map.get(Thread.currentThread());
System.out.println("B form "+Thread.currentThread().getName()
+"...get data :"+data);
}
}
}
总结:每个线程属于自己的线程数据,就是存进去的数据是存到线程中。
当前线程去存入数据和取数据,取出来的数据是存入的数据。(不管是不是静态)
(自定义线程范围内的共享数据,也称为线程数据。)
package com.itheima.study;
import java.util.Random;
/*
* 线程范围内的共享数据。ThreadLocal,相当于一个集合。
* 注意:一个ThreadLocal只能存储一个变量或者对象。
* 如果有多个数据要进行存储,那么可以把他们封装成对象进行存储。*如果有多个对象要进行存储,那么可以把他们封装成集合进行存储。
* */
public class ThreadLocalTest {
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
public static void main(String... args) {
for (int x = 1; x <= 2; x++) {
new Thread(new Runnable() {
@Override
public void run() {
int data = new Random().nextInt();
threadLocal.set(data);
System.out.println(Thread.currentThread().getName()
+ "...." + data);
new A().get();
new B().get();
}
}).start();
}
}
static class A {
public void get() {
int data = threadLocal.get();
System.out.println("A form " +Thread.currentThread().getName()
+ "...get data :" + data);
}
}
static class B {
public void get() {
int data = threadLocal.get();
System.out.println("B form " + Thread.currentThread().getName()
+ "...get data :" + data);
}
}
}
(线程范围内的共享数据,封装成对象。单例设计模式)
package com.itheima.study;
import java.util.Random;
/*
* 线程范围内的共享数据。
* ThreadLocal相当于一个集合,数据存储到当前线程里面去了。
* 如果要给当前的线程设置值用当前线程的set方法。
* 如果要获取当前线程设置好的值,用当前线程的get方法。
* 数据如果多了,那么就把数据包装成一个对象。
* 注意:ThreadLocal只能存储一个对象,或者把对象存入集合中。
*/
/*
* 单例设计模式:饿汉式
* private Person (){}
* private static final Person Instance = new Person();
* public static Person getInstance(){* return Instance;
* }
*/
/*
* 说实话,我这视频看了俩次,第一次我对张孝祥老师的视频感觉就是看起来太抽象了。
* 结果,我对张孝祥老师的视频进行了第二次。感觉第二次的收获挺大的。
* 发现原因:原来第一次是我太不专心听了,所以导致了听不懂。
*/
/*
* ThreadLocal跟单例很像。
* 所以就采用了单例跟ThreadLocal融合在一起了,把类写成单例,
* 获取单例的实例对象的时候,其实就是获取当前线程的对象,
* 然后就可以对当前的对象进行操作,比如设置值,获取值。
*/
class Person {
private static ThreadLocal
threadLocal = new ThreadLocal ();
private String name;
private int age;
/*
* 单例设计模式:懒汉式
* */
private Person(){}
/*
* private static Person Instance = null;
* 下面代码相当与这句,也就是获取对象的实例话对象。
* 如果没有对对象进行初始化值,那么该值就会返回null。
* 但是这里是获取当前线程的实例对象。
* */
public static Person getInstance(){
/*
* 由于的线程对象,所以必须保证每个线程对象都有一份
* */
Person Instance = threadLocal.get();
if(Instance ==null){
synchronized(Person.class){
if(Instance==null){
//对象是空的话,那么就对对象进行实例化。
Instance = new Person();
//把对象设置进当前线程。
threadLocal.set(Instance);
}
}
}
//返回当前线程对象
return Instance;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
public class PersonThreadLocalTest {
private static int data ;
public static void main(String... args) {
new PersonThreadLocalTest().init();
}
public void init(){
for(int x=1;x<=5;++x){
new Thread(new Runnable(){
@Override
public void run() {
int data = (int)new Random().nextInt(12)+18;
//获取当前线程的对象。
Person p = Person.getInstance();
//给当前线程对象的age进行设置。
p.setAge(data);
//给当前线程对象的name进行设置。
p.setName("程序员——新长城");
new A().getData();
new B().getData();
}
}).start();
}
}
class A{
public void getData(){
/*
* 获取当前线程对应对象的值,
* 线程对象set方法对应线程对象get方法。
* 设置进去什么,就获取出来什么。
* */
Person p = Person.getInstance();
System.out.println("A "+Thread.currentThread().getName()+
"姓名:"+p.getName()+
"...年龄:"+p.getAge());
}
}
class B{
public void getData(){
Person p = Person.getInstance();
System.out.println("B "+Thread.currentThread().getName()+
"姓名:"+p.getName()+
"...年龄:"+p.getAge());
}
}
(数据类型多线程并发操作)}
package com.itheima.study;
import java.util.concurrent.atomic.AtomicInteger;
/*
多线程同步并发库 基本数据操作。
*/
public class atomicIntegerTest {
public static void main(String... args) {
AtomicInteger atomicInteger =new AtomicInteger();
atomicInteger.set(20);
atomicInteger.addAndGet(20);
System.out.println(atomicInteger);
}
}
(线程池)
package com.itheima.study;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadPoolTest {
public static void main(String... args) {
ExecutorService executorService =
Executors.newSingleThreadExecutor();//单一线程池
//Executors.newCachedThreadPool();//缓存线程池
//Executors.newFixedThreadPool(3);//固定大小线程池
for(int x=1;x<=10;x++){
final int task = x;
executorService.execute(new Runnable(){
@Override
public void run() {
for(int y=1;y<=10;y++){
System.out.println(Thread.currentThread().getName()
+" is looping of " + y +" for task of "+task );
}
}
});
}
System.out.println("over");
//executorService.shutdown();//顺序关闭
//executorService.shutdownNow();//空闲时关闭线程池
/*
* 相当于TraditionThread的炸弹一样。
* */
Executors.newScheduledThreadPool(3).schedule(
new Runnable(){
public void run(){
System.out.println("bombing");
}
},
5,
TimeUnit.SECONDS);
/*
* 连环爆炸。
* */
Executors.newScheduledThreadPool(3).scheduleAtFixedRate(
new Runnable(){
public void run(){
System.out.println("bombing");
}
},
5,
2,
TimeUnit.SECONDS);
}
}
package com.itheima.study;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class CallableAndFuture {
public static void main(String... args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<String> re = threadPool.submit(new Callable<String>(){
@Override
public String call() throws Exception {
return "程序员";
}
});
try {
System.out.println("获取结果:等待2秒");
Thread.sleep(2000);
System.out.println("结果为:"+re.get());
System.out.println("结果为:"+re.get(0,TimeUnit.SECONDS));
}catch(Exception e) {
e.printStackTrace();
}
ExecutorService threadPool2 = Executors.newFixedThreadPool(10);
CompletionService<Integer> completionService =new ExecutorCompletionService<Integer>(threadPool2);
for(int i=1;i<=10;i++){
final int value = i;
completionService.submit(new Callable<Integer>(){
@Override
public Integer call() throws Exception {
Thread.sleep(new Random().nextInt(5000));
return value;
}
});
}
for(int i=1;i<=10;i++){
try {
System.out.println(completionService.take().get());
} catch (Exceptione) {
e.printStackTrace();
}
}
}
}