线程创建的两种方式:继承runnable接口或Thread类
有了Thread类为什么还要runnable接口?
因为java是单继承的,不能同时继承多个类,所以为了让一个类能继承其他类的特性,所以需要利用接口。
线程可以有6种状态
- 新建(new一个线程类)---线程还没开始运行线程中的代码,运行之前有一些基础工作要做
- 可运行(Runnable)--start()方法之后
- 被阻塞(Blocked)
- 等待(Waiting)
- 计时等待(Timed waiting)
- 终止(Terminated)--run运行结束正常死亡 或 一个没有捕获的异常终止了run方法
Thread类常用方法
join()----- Waits for this thread to die. 让当前Thread加入到t.join(),意味着线程t运行结束之前,当前Thread不会运行。
讲解参考:http://uule.iteye.com/blog/1101994
sleep(long millis)--Causes the currently executing thread to sleep for the specified number of milliseconds 不会让线程释放它所持有的同步锁;而且在这期间它也不会阻碍其它线程的运行
wait(long timeout)--这个继承Object对象 Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed 当调用了某个对象的wait()方法时,当前运行的线程就会转入WAITING状态,等待别的线程再次调用这个对象的notify()或者notifyAll()方法唤醒它,或者到了指定的最大等待时间,线程自动醒来。如果线程调用了某个对象的wait()方法,这个线程就会释放这个对象所持有的同步资源(不会释放其他对象的同步锁)
yeid()--A hint to the scheduler that the current thread is willing to yield its current use of a processor.让当前运行Thread放弃其所占用的cpu时间片,以便让其他Thread运行,但是仍有可能被jvm选中
interrupt()--Interrupts this thread
notify()--也是继承object类 Wakes up a single thread that is waiting on this object's monitor
参考:http://blog.csdn.net/tayanxunhua/article/details/20528475
***************************************************************************************************************
synchronized关键字
采用 synchronized 修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁
互斥是实现同步的一种手段,临界区、互斥量和信号量都是主要的互斥实现方式。synchronized 关键字经过编译后,会在同步块的前后分别形成 monitorenter 和 monitorexit 这两个字节码指令。根据虚拟机规范的要求,在执行 monitorenter 指令时,首先要尝试获取对象的锁,如果获得了锁,把锁的计数器加 1,相应地,在执行 monitorexit 指令时会将锁计数器减 1,当计数器为 0 时,锁便被释放了。由于 synchronized 同步块对同一个线程是可重入的,因此一个线程可以多次获得同一个对象的互斥锁,同样,要释放相应次数的该互斥锁,才能最终释放掉该锁
public synchronized void method() {//锁住这个方法
//something
}
public void method(){
synchronized(this){//this 代表锁住当前类的对象 不是类
//something
}
}
在synchronized里有的时候会用到wait(),notify() ,notifyAll().
题目:子线程循环10次 主线程循环100次 接着子线程循环10次 主线程循环100次 如此反复50次
ublic class MyThread {
public static void main(String[] args){
final Test1 test=new Test1();
new Thread(new Runnable(){
public void run(){
for(int i=1;i<=50;i++){
test.sub();
}
}
}).start();
for(int i=1;i<=50;i++){
test.main();
}
}
}
class Test1{
public Test1(){
}
private boolean beSub=true;
public synchronized void sub(){
while(beSub!=true){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i=1;i<=10;i++){
System.out.println("sub-----"+i);
}
beSub=false;
this.notify();//当beSub=false,之前main方法里有等待的 用这个唤醒
}
public synchronized void main(){
System.out.println(beSub);
while(beSub==true){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i=1;i<=100;i++){
System.out.println("main-----"+i);
}
beSub=true;
this.notify();//用来唤醒sub方法
}
}
*******************************************************************************************************************************
ThreadLocal<T>
用于线程共享数据,使得共享数据更加方便了
常用API
public T get()// Returns the value in the current thread's copy of this thread-local variable.
public void set(T value)//Sets the current thread's copy of this thread-local variable to the specified value.
public void remove()//Removes the current thread's value for this thread-local variable.
*****************************************************************************************************************
原子类
java.util.concurrent.atomic包 可以对基本数据 数组中的基本数据 对象中的基本数据等进行操作
以Integet为例
类AtomicInteger
An int value that may be updated atomically.
类AtomicIntegerArray
An int array in which elements may be updated atomically.
类AtomicIntegerFieldUpdater<T>
A reflection-based utility that enables atomic updates to designated volatile int fields of designated classes.
在AtomicIntegerFieldUpdater中注意这个方法
static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName)
Creates and returns an updater for objects with the given field.
******************************************************************************************************************************
线程池
讲解:
首先介绍在TCP服务器编程模型的原理,每一个客户端连接用一个单独的线程 叫做服务 当客户端会话结束时线程也结束,即每次来一个新的客户端 服务器就得创建一个新的线程。如果访问服务器的客户端很多 那么服务器就要不断的创建和销毁线程 这个会影响服务器性能,为此,可以先创建一些线程 他们的集合称为线程池 当服务器接收到一个客户端的请求时就从线程池中取出一个空闲的线程为之服务,服务完不关闭线程 而是将线程返回原来的线程池
//ExecutorService threadPool=Executors.newFixedThreadPool(3);
//ExecutorService threadPool=Executors.newCachedThreadPool();//里面的线程数动态变化的
//只有一个线程。(如果里面线程死了 它会自动新开一个线程 就是一定要有一个线程在里面)
ExecutorService threadPool=Executors.newSingleThreadExecutor();
for(int i=1;i<=10;i++){
final int task=i;
threadPool.submit(new Runnable(){
public void run() {
for(int j=1;j<=10;j++){
System.out.println(Thread.currentThread().getName()+
" is looping of "+j+" for task of "+task);
}
}
});
}
System.out.println("all of ten tasks have been committed");
//threadPool.shutdown();
//定时器线程
//Creates a thread pool that can schedule commands to run after a
// given delay, or to execute periodically.
//这个是在6秒后执行
Executors.newScheduledThreadPool(3).schedule(new Runnable(){
public void run(){
System.out.println("bombing");
}
}, 6, TimeUnit.SECONDS);
//6秒之后开启线程 之后每个2秒运行一次
Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable(){
public void run(){
System.out.println("bombing");
}
}, 6,2, TimeUnit.SECONDS);
*************************************************************************************************************************
Callable 和 Future
线程执行后返回的结果
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());
//一秒内得不到结果 则抛出异常
//System.out.println("拿到结果: "+future.get(1,TimeUnit.SECONDS));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//completionService用于提交一组Callable任务 其task方法返回已经完成的一个callable任务对应的future对象
ExecutorService pool=Executors.newFixedThreadPool(10);
CompletionService<Integer> service=new ExecutorCompletionService<Integer>(pool);
for(int i=1;i<=10;i++){
final int req=i;
service.submit(new Callable<Integer>(){
public Integer call() throws Exception {
Thread.sleep(new Random().nextInt(5000));
return req;
}
});
}
for(int i=1;i<=10;i++){
//谁先运行完 先返回谁
try {
System.out.println(service.take().get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
*************************************************************************************************************************
Lock 和condition实现线程同步通信
Lock比synchronized更加面向对象
condition的功能类似传统线程技术中的Objce.wait和Object.notify。等待condition时允许”虚假唤醒“
Lock lock=new ReentrantLock();
public void method(){
lock.lock();
try{
//something
}catch(Exception e){
lock.unlock();
}
}
API里给的案例
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
读写锁 ReentrantReadWriteLock
多个读锁不互斥 读锁与写锁互斥 写锁与写锁互斥
缓存demo
public class CacheDemo {
private Map<String,Object> cache=new HashMap<String,Object>();
private ReadWriteLock rw1=new ReentrantReadWriteLock();
public Object getData(String key){
rw1.readLock().lock();
Object data=null;
try{
data=cache.get(key);
if(data==null){
rw1.readLock().unlock();
rw1.writeLock().lock();
try{
data="dddd";//实际上是去查询数据
}finally{
rw1.writeLock().unlock();
}
}
rw1.readLock().lock();
}finally{
rw1.readLock().unlock();
}
return data;
}
}
**************************************************************************************************************************************
Semaphore 信号灯
维护访问自身的线程个数 并提供同步机制
ExecutorService pool=Executors.newCachedThreadPool();
final Semaphore sp=new Semaphore(3);//允许3个灯
for(int i=1;i<=10;i++){
Runnable run=new Runnable(){
public void run(){
try{
sp.acquire();//获取灯
}catch(Exception e){
e.printStackTrace();
}
System.out.println("线程 "+Thread.currentThread().getName()+"进入,当前已有"+(3-sp.availablePermits())+"并发");
try{
Thread.sleep((long)Math.random()*10000);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("线程 "+Thread.currentThread().getName()+"即将离开");
sp.release();//释放灯
}
};
pool.execute(run);
CyclicBarrier
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
ExecutorService pool=Executors.newCachedThreadPool();
final CyclicBarrier cb=new CyclicBarrier(3);
for(int i=1;i<=3;i++){
Runnable run=new Runnable(){
public void run(){
try{
Thread.sleep((long)Math.random()*10000);
System.out.println("线程 "+Thread.currentThread().getName()+"即将到达集合点1,当前已有"+
(cb.getNumberWaiting()+1)+"已经到达,"+ (cb.getNumberWaiting()==2 ?"都到齐了,继续走":"正在等候"));
cb.await();
Thread.sleep((long)Math.random()*10000);
System.out.println("线程 "+Thread.currentThread().getName()+"即将到达集合点2,当前已有"+
(cb.getNumberWaiting()+1)+"已经到达,"+ (cb.getNumberWaiting()==2 ?"都到齐了,继续走":"正在等候"));
cb.await();
Thread.sleep((long)Math.random()*10000);
System.out.println("线程 "+Thread.currentThread().getName()+"即将到达集合点3,当前已有"+
(cb.getNumberWaiting()+1)+"已经到达,"+ (cb.getNumberWaiting()==2 ?"都到齐了,继续走":"正在等候"));
cb.await();
}catch(Exception e){
e.printStackTrace();
}
}
};
pool.execute(run);
}
pool.shutdown();