标签:
一,线程同步与互斥
例如:线程一执行10次,接着线程二执行20次,如此往来9次。
public class Demo05 {
public static void main(String[] args) {
new Demo05().init();
}
private void init(){
final Inner inner=new Inner(); //两个线程拿到的锁对象都是同一个
//线程一
new Thread(new Runnable() {
@Override
public void run() {
for(int i=1;i<10;i++){
inner.sub(i);
}
}
}).start();
//线程二
new Thread(new Runnable() {
@Override
public void run() {
for(int i=1;i<10;i++){
inner.main(i);
}
}
}).start();
}
//成员内部类
class Inner{
private boolean subShouble=true;//是否要子线程执行
private synchronized void sub(int i){
while(!subShouble){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=1;j<=10;j++){
System.out.println("线程一执行"+j+",第"+i+"次;");
}
subShouble=false;
this.notify();
}
private synchronized void main(int i){
while(subShouble){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=1;j<=20;j++){
System.out.println("线程二执行"+j+",第"+i+"次;");
}
subShouble=true;
this.notify();
}
}
}
二,线程范围内的共享变量
例如1:
public class Demo05 {
private static ThreadLocal<Integer> tLocal=new ThreadLocal<Integer>();
public static void main(String[] args) {
for(int i=0;i<2;i++){
new Thread(new Runnable() {
@Override
public void run() {
int data=new Random().nextInt();
tLocal.set(data);
System.out.println(Thread.currentThread().getName()+"向data变量中放了"+data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get(){
int data=tLocal.get();
System.out.println("A 在"+Thread.currentThread().getName()+" 取出静态变量data是:"+data);
}
}
static class B{
public void get(){
int data=tLocal.get();
System.out.println("B 在"+Thread.currentThread().getName()+" 取出静态变量data是:"+data);
}
}
}
例如2:
public class Demo05 {
public static void main(String[] args) {
//线程1
new Thread(new Runnable() {
@Override
public void run() {
ServerContainer.getInstance().setName("杨灿");
ServerContainer.getInstance().setAge(26);
System.out.println(Thread.currentThread().getName()+"放的数据是杨灿和26");
new A().get();
}
}).start();
//线程2
new Thread(new Runnable() {
@Override
public void run() {
ServerContainer.getInstance().setName("杨灿");
ServerContainer.getInstance().setAge(66);
System.out.println(Thread.currentThread().getName()+"放的数据是杨灿和66");
new B().get();
}
}).start();
}
static class A{
public void get(){
String name=ServerContainer.getInstance().getName();
int age=ServerContainer.getInstance().getAge();
System.out.println("A..."+Thread.currentThread().getName()+"获取的数据是"+name+",,,,,"+age);
}
}
static class B{
public void get(){
String name=ServerContainer.getInstance().getName();
int age=ServerContainer.getInstance().getAge();
System.out.println("B..."+Thread.currentThread().getName()+"获取的数据是"+name+",,,,,"+age);
}
}
}
/**
* 每一个线程对应自己的一个ServerContainer对象
* @author yangcan
*
*/
class ServerContainer{
private String name;
private int age;
private static ThreadLocal<ServerContainer> scLocal=new ThreadLocal<ServerContainer>();
private ServerContainer(){
}
public static ServerContainer getInstance(){
ServerContainer serverContainer=scLocal.get();//先从scLocal取出对象
if(serverContainer==null){
serverContainer=new ServerContainer();
scLocal.set(serverContainer);
}
return serverContainer;
}
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;
}
}
三,线程池
ExecutorService ex=Executors.newFixedThreadPool(3);//创建固定线程数的线程池
for(int i=0;i<10;i++){ //分配10个任务给线程池
final int task=i;
ex.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+",,,"+task);
}
});
}
四,Java5中的锁
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo05 {
public static void main(String[] args) {
new Demo05().init();
}
public void init(){
final Inner inner=new Inner();
//线程一
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<100;i++){
inner.printString("yangcan");
}
}
}).start();
//线程二
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<100;i++){
inner.printString("likeqiang");
}
}
}).start();
}
class Inner{
Lock lock=new ReentrantLock();
public void printString(String name){
lock.lock();
try {
for(int i=0;i<name.length();i++){
System.out.print(name.charAt(i));
}
System.out.println();
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
五,读写锁
读写互斥、写写互斥
public class ReadWriteLockTest {
public static void main(String[] args) {
final Queue3 q3 = new Queue3();
//3个线程读,3个线程写
for (int i=0; i < 3; i++) {
new Thread() {
public void run() {
while (true) {
q3.get();
}
}
}.start();
new Thread() {
public void run() {
while (true) {
//传入一个data值
q3.put(new Random().nextInt(10000));
}
}
}.start();
}
}
}
class Queue3{
private Object data = null;//共享数据
private ReentrantReadWriteLock rw1 = new ReentrantReadWriteLock();//读写锁
/**
* 读数据
*/
public void get(){
rw1.readLock().lock();
System.out.println(Thread.currentThread().getName()+"大家注意了, 要准备开始读数据了!");
try{
Thread.sleep((long) (Math.random()*1000));
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"已经取到的数据是: " + data);
rw1.readLock().unlock();
}
/**
* 写数据
* @param data
*/
public void put(Object data){
rw1.writeLock().lock();
System.out.println(Thread.currentThread().getName()+" 朋友们,我要开始写数据了!我要写的数据是:"+data);
try{
Thread.sleep((long) (Math.random()*1000));
}catch (Exception e) {
e.printStackTrace();
}
this.data = data;
System.out.println(Thread.currentThread().getName()+"已经写的数据是: "+ data);
rw1.writeLock().unlock();
}
}
运行结果:
Thread-0大家注意了, 要准备开始读数据了!
Thread-2大家注意了, 要准备开始读数据了!
Thread-4大家注意了, 要准备开始读数据了!
Thread-4已经取到的数据是: null
Thread-0已经取到的数据是: null
Thread-2已经取到的数据是: null
以上表明在读的时候,没有人来写
Thread-3 朋友们,我要开始写数据了!我要写的数据是:7934
Thread-3已经写的数据是: 7934
Thread-5 朋友们,我要开始写数据了!我要写的数据是:9921
Thread-5已经写的数据是: 9921
Thread-1 朋友们,我要开始写数据了!我要写的数据是:8551
Thread-1已经写的数据是: 8551
以上表明在写的时候没有别的线程来写
Thread-4大家注意了, 要准备开始读数据了!
Thread-0大家注意了, 要准备开始读数据了!
Thread-2大家注意了, 要准备开始读数据了!
Thread-0已经取到的数据是: 8551
Thread-2已经取到的数据是: 8551
Thread-4已经取到的数据是: 8551
Thread-3 朋友们,我要开始写数据了!我要写的数据是:1074
Thread-3已经写的数据是: 1074
Thread-5 朋友们,我要开始写数据了!我要写的数据是:4540
Thread-5已经写的数据是: 4540
Thread-1 朋友们,我要开始写数据了!我要写的数据是:1273
Thread-1已经写的数据是: 1273
Thread-0大家注意了, 要准备开始读数据了!
Thread-2大家注意了, 要准备开始读数据了!
Thread-4大家注意了, 要准备开始读数据了!
Thread-2已经取到的数据是: 1273
Thread-0已经取到的数据是: 1273
Thread-4已经取到的数据是: 1273
六,Condition
Lock下的线程通信,相当于wait()和notify
例如:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 阻塞队列
* sub1打印5次,接下来sub2打印5次,再接下来main打印5次,如此往来10次
* @author yangcan
*
*/
public class DuiLie {
public static void main(String[] args) {
final Bussiness bussiness=new Bussiness();
//sub1
new Thread(new Runnable() {
public void run() {
for(int i=0;i<10;i++){
bussiness.sub1(i);
}
}
}).start();
//sub2
new Thread(new Runnable() {
public void run() {
for(int i=0;i<10;i++){
bussiness.sub2(i);
}
}
}).start();
//主线程
for(int i=0;i<10;i++){
bussiness.main(i);
}
}
static class Bussiness{
private Lock lock=new ReentrantLock();
private Condition conditionSub1=lock.newCondition();
private Condition conditionSub2=lock.newCondition();
private Condition conditionMain=lock.newCondition();
private int shoubeSub1=1;
public void sub1(int i){
lock.lock();
try{
while(shoubeSub1!=1){
conditionSub1.await();
}
for(int j=0;j<5;j++){
System.out.println("sub1内打印"+j+"次,共"+i+"次");
}
shoubeSub1=2;
conditionSub2.signal();
}catch(Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void sub2(int i){
lock.lock();
try{
while(shoubeSub1!=2){
conditionSub2.await();
}
for(int j=0;j<5;j++){
System.out.println("sub2内打印"+j+"次,公"+i+"次");
}
shoubeSub1=3;
conditionMain.signal();
}catch(Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void main(int i){
lock.lock();
try{
while(shoubeSub1!=3){
conditionMain.await();
}
for(int j=0;j<5;j++){
System.out.println("main内打印"+j+"次,公"+i+"次");
}
shoubeSub1=1;
conditionSub1.signal();
}catch(Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
七,多个线程互斥。
比如:一个文件同时只允许3个线程访问,当第4个线程来访问的时候要等待。
java5中提供了一个semaphore来实现这个机制。
ExecutorService ex=Executors.newCachedThreadPool();
final Semaphore sem=new Semaphore(3);//3个信号灯
for(int i=1;i<=10;i++){
Runnable runnable=new Runnable() {
@Override
public void run() {
try {
sem.acquire();//进来一个线程,拿掉一个信号灯
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName()+"进入,当前已有"+(3-sem.availablePermits())+"并发");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName()+"已经离开,当前有"+(3-sem.availablePermits())+"并发");
sem.release();//访问之后,释放信号灯
}
};
ex.execute(runnable);
}
ex.shutdown();
执行结果:
线程pool-1-thread-1进入,当前已有3并发
线程pool-1-thread-2进入,当前已有3并发
线程pool-1-thread-3进入,当前已有3并发
线程pool-1-thread-2已经离开,当前有3并发
线程pool-1-thread-1已经离开,当前有3并发
线程pool-1-thread-3已经离开,当前有3并发
线程pool-1-thread-4进入,当前已有2并发
线程pool-1-thread-6进入,当前已有3并发
线程pool-1-thread-5进入,当前已有3并发
线程pool-1-thread-4已经离开,当前有3并发
线程pool-1-thread-6已经离开,当前有3并发
线程pool-1-thread-7进入,当前已有3并发
线程pool-1-thread-5已经离开,当前有3并发
线程pool-1-thread-8进入,当前已有3并发
线程pool-1-thread-9进入,当前已有3并发
线程pool-1-thread-7已经离开,当前有3并发
线程pool-1-thread-9已经离开,当前有3并发
线程pool-1-thread-8已经离开,当前有3并发
线程pool-1-thread-10进入,当前已有3并发
线程pool-1-thread-10已经离开,当前有1并发
八,阻塞队列实现类
ArrayBlockingQueue
例如:
final BlockingQueue queue = new ArrayBlockingQueue(20);
//线程1是放数据,如果满了就阻塞
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
// 将指定元素添加到此队列中,如果没有可用空间,将一直等待(如果有必要)。
try {
queue.put(i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("向阻塞队列中添加了元素:" + i);
}
}
}).start();
//线程2是取数据,如果没有数据就阻塞
new Thread(new Runnable() {
@Override
public void run() {
try {
while(true){
Thread.sleep(2000);
System.out.println("开始取数据了。。。");
Object object=queue.take();//没有数据的时候就阻塞
System.out.println("取出的数据是:"+object);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
运行结果:
向阻塞队列中添加了元素:0
向阻塞队列中添加了元素:1
向阻塞队列中添加了元素:2
向阻塞队列中添加了元素:3
向阻塞队列中添加了元素:4
向阻塞队列中添加了元素:5
向阻塞队列中添加了元素:6
向阻塞队列中添加了元素:7
向阻塞队列中添加了元素:8
向阻塞队列中添加了元素:9
向阻塞队列中添加了元素:10
向阻塞队列中添加了元素:11
向阻塞队列中添加了元素:12
向阻塞队列中添加了元素:13
向阻塞队列中添加了元素:14
向阻塞队列中添加了元素:15
向阻塞队列中添加了元素:16
向阻塞队列中添加了元素:17
向阻塞队列中添加了元素:18
向阻塞队列中添加了元素:19
开始取数据了。。。
向阻塞队列中添加了元素:20
取出的数据是:0
开始取数据了。。。
向阻塞队列中添加了元素:21
取出的数据是:1
开始取数据了。。。
向阻塞队列中添加了元素:22
取出的数据是:2
开始取数据了。。。
向阻塞队列中添加了元素:23
取出的数据是:3
开始取数据了。。。
向阻塞队列中添加了元素:24
取出的数据是:4
开始取数据了。。。
向阻塞队列中添加了元素:25
取出的数据是:5
开始取数据了。。。
向阻塞队列中添加了元素:26
取出的数据是:6
开始取数据了。。。
取出的数据是:7
向阻塞队列中添加了元素:27
开始取数据了。。。
取出的数据是:8
向阻塞队列中添加了元素:28
开始取数据了。。。
向阻塞队列中添加了元素:29
取出的数据是:9
开始取数据了。。。
取出的数据是:10
开始取数据了。。。
取出的数据是:11
开始取数据了。。。
取出的数据是:12
开始取数据了。。。
取出的数据是:13
开始取数据了。。。
取出的数据是:14
开始取数据了。。。
取出的数据是:15
开始取数据了。。。
取出的数据是:16
开始取数据了。。。
取出的数据是:17
开始取数据了。。。
取出的数据是:18
开始取数据了。。。
取出的数据是:19
开始取数据了。。。
取出的数据是:20
开始取数据了。。。
取出的数据是:21
开始取数据了。。。
取出的数据是:22
开始取数据了。。。
取出的数据是:23
开始取数据了。。。
取出的数据是:24
开始取数据了。。。
取出的数据是:25
开始取数据了。。。
取出的数据是:26
开始取数据了。。。
取出的数据是:27
开始取数据了。。。
取出的数据是:28
开始取数据了。。。
取出的数据是:29
开始取数据了。。。
标签:
原文地址:http://www.cnblogs.com/xxgyangcan/p/5175933.html