1. 线程创建方式
1. new Thread(new Runnable(){}).start();2. new Thread(){public void run(){}}.start();
第一种方式更符合面向对象,因为将线程与线程运行的对象分来了
2. synchronized关键字,用于实现代码互斥,多线程时,这段代码同一时间只有一个线程可以访问
可以修饰代码块或者方法3. 传统线程同步通信技术
package com.wzz.xiancheng;
/**
* 子线程运行10次,主线程运行100次,如此循环50次
* @author wzz
*
*/
public class TrainThreadComm {
public static void main(String[] args) {
final ExecData data = new ExecData();
//子线程
new Thread(new Runnable(){
@Override
public void run() {
for(int i=0; i<50; i++){
data.dataSub(i);
}
}
}).start();
//主线程
for(int i=0; i<50; i++){
data.dataMain(i);
}
}
}
class ExecData{
private boolean flag = true;
private String data = "aaa";
/*
* 子线程运行
*/
public synchronized void dataSub(int k){
while(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0; i<10; i++){
System.out.println(k+"_子线程运行:"+data+",第"+i+"次");
}
this.flag = false;
this.notify();
}
/*
* 主线程运行
*/
public synchronized void dataMain(int k){
while(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0; i<100; i++){
System.out.println(k+"_主线程运行:"+data+",第"+i+"次");
}
this.flag = true;
this.notify();
}
}
1. 讲需要操作的数据和操作方法封装在一个类中,然后实例化对象后,新建线程去访问
2. 利用notify()和wait()方法进行运行和等待的调度
3. bool变量设定执行顺序
4. 线程范围内共享变量的概念与作用
package com.wzz.xiancheng;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ThreadShareDataUseMap {
private static Map<Thread, String> map = new HashMap();
public static void main(String[] args) {
for(int i=0; i<2; i++){
new Thread(new Runnable(){
@Override
public void run() {
map.put(Thread.currentThread(), new Random().nextInt()+"");
A.get();
B.get();
}
}).start();
}
}
static class A{
public static void get(){
String data = map.get(Thread.currentThread());
System.out.println("A:"+Thread.currentThread().getId()+","+data);
}
}
static class B{
public static void get(){
String data = map.get(Thread.currentThread());
System.out.println("B:"+Thread.currentThread().getId()+","+data);
}
}
}
1. 利用map,线程为key,数据为value
5. ThreadLocal类及应用技巧
package com.wzz.ttt;
import java.util.Random;
public class ThreadS {
public static void main(String[] args) {
for(int i=0; i<3; i++){
new Thread(new Runnable() {
@Override
public void run() {
MyThreadScopeData.getThreadInstance().setAge(new Random().nextInt(100));
MyThreadScopeData.getThreadInstance().setName(Thread.currentThread().getName());
get();
}
}).start();
}
}
public static void get(){
int age = MyThreadScopeData.getThreadInstance().getAge();
String name = MyThreadScopeData.getThreadInstance().getName();
System.out.println(name+":"+age);
}
}
class MyThreadScopeData{
private MyThreadScopeData(){}
public static /*synchronized*/ MyThreadScopeData getThreadInstance(){
MyThreadScopeData instance = map.get();
if(instance == null){
instance = new MyThreadScopeData();
map.set(instance);
}
return instance;
}
//private static MyThreadScopeData instance = null;//new MyThreadScopeData();
private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
1. ThreadLocal类来共享数据,
6. 多线程数据共享
package com.wzz.xiancheng;
/**
* 两个线程,一个++,一个--
* @author wzz
*
*/
public class MultiThreadShareData {
private static ShareData1 data1 = new ShareData1();
public static void main(String[] args) {
ShareData1 data2 = new ShareData1();
/*
* 写两个runnable
*/
new Thread(new MyRunnable1(data2)).start();
new Thread(new MyRunnable2(data2)).start();
/*
* 直接调用数据的方法
*/
final ShareData1 data1 = new ShareData1();
new Thread(new Runnable(){
@Override
public void run() {
data1.decrement();
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
data1.increment();
}
}).start();
}
}
/**
* ++线程runnnable
* @author wzz
*
*/
class MyRunnable1 implements Runnable{
private ShareData1 data1;
public MyRunnable1(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.decrement();
}
}
/**
* --线程runnable
* @author wzz
*
*/
class MyRunnable2 implements Runnable{
private ShareData1 data1;
public MyRunnable2(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.increment();
}
}
class ShareData1{
private int j = 0;
public synchronized void increment(){
j++;
}
public synchronized void decrement(){
j--;
}
}
1. 把数据操作封装成一个类,并实例化
2. 可以实例化数据类后,线程直接调用对象的操作方法
3. 也可以将不通的操作放入不同的runnable对象
7. java5原子性操作类的应用
AtominInteger ai = new AtominInteger();
Atomin*******
8. java5线程并发库的应用
线程池:<span style="white-space:pre"> </span>public static void main(String[] args) {
//ExecutorService threadPool = Executors.newFixedThreadPool(3);//固定数量
//ExecutorService threadPool = Executors.newCachedThreadPool();//缓冲型,根据需要新建多个线程,不需要时候再释放掉
ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程,当线程死掉时,重启一条新的线程
for(int i=0; i<10; i++){
final int k = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId()+"_"+k);
}
});
}
threadPool.shutdown();//当线程都完成时,关掉线程池
//threadPool.shutdownNow();//立即关掉线程池
}
9. CallableAndFuture
代码见---9. CallableAndFuture
/*
单一任务的
*/
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<String> future =
threadPool.submit(
new Callable<String>() {
public String call() throws Exception {//这里面写线程任务代码
Thread.sleep(2000);
return "hello";
};
}
);
System.out.println("等待结果");
try {
System.out.println("拿到结果:" + future.get());//get方法会在线程执行完毕后才执行
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
批量放入多个线程,并取出多个结果,取出顺序按照线程执行顺序
*/
ExecutorService threadPool2 = Executors.newFixedThreadPool(10);
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);
for(int i=1;i<=10;i++){
final int seq = i;
completionService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(new Random().nextInt(5000));
return seq;
}
});
}
for(int i=0;i<10;i++){
try {
System.out.println(
completionService.take().get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
10. java5的线程锁技术
相当于synchronized,但是更符合面向对象
Lock lock = new ReentrantLock();
lock.lock();
lock.unlock();
11. 读写锁的使用
读与读之间可以并,读写,写与写互斥
ReadWriteLock rwl = new ReentrantReadWriteLock();
rwl.readLock().lock();
rwl.readLock().unlock();
rwl.writeLock().lock();
rwl.writeLock().unlock();
一个缓存器的例子,代码见---10. 一个缓存器的例子
public class CacheDemo {
private Map<String, Object> cache = new HashMap<String, Object>();
public static void main(String[] args) {
}
private ReadWriteLock rwl = new ReentrantReadWriteLock();
public Object getData(String key){
rwl.readLock().lock();
Object value = null;
try{
value = cache.get(key);
if(value == null){
rwl.readLock().unlock();
rwl.writeLock().lock();
try{
if(value==null){
value = "aaaa";//实际失去queryDB();
}
}finally{
rwl.writeLock().unlock();
}
rwl.readLock().lock();
}
}finally{
rwl.readLock().unlock();
}
return value;
}
}
12. Condition
1. 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法Lock lock = new ReentrantLock();
Conditicon con = lock.newCondition();
2. Condition 应该总是在一个循环中被等待,并测试正被等待的状态声明
while (count == items.length) {
con.await();
}
3. 主要方法
1. await() 造成当前线程在接到信号或被中断之前一直处于等待状态。
2. signal() 唤醒一个等待线程。
3. signalAll() 唤醒所有等待线程。
方法类似于(wait、notify 和 notifyAll)