黑马程序员 Java面向对象——JDK 1.5 线程并发库


---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

面向对象

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<name.length();x++){

System.out.print(name.charAt(x));

}

System.out.println();

}

}

public synchronized void output2(String name){

for(int x=0;x<name.length();x++){

System.out.print(name.charAt(x));

}

System.out.println();

}

public static synchronized void output3(String name){

for(int x=0;x<name.length();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<Person> threadLocal = new ThreadLocal<Person>();

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();

}

}

}

}

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

相关内容

    暂无相关文章