Thread

>>//一个简单Thread缓冲池的实现  
/*
Queue的一个经典实现是使用一个循环数组(这个实现在很多数据结构的书上都有介绍),如一个大小为size的数组,这个循环数组可以被想象成首尾相连的一个环。oldest指向Queue中最老的数据所在的位置,next指向下一个可以放新数据的位置。
放入一个新数据到next的位置后,需要更新next:next = (next + 1) % size;
从oldest位置取出一个数据后,需要更新oldest:oldest = (oldest + 1) % size;
当oldest == next的时候,Queue为空,
当(next + 1) % size == oldest的时候,Queue为满。
(注意: 为了区分Queue为空和为满的情况,实际上Queue里面最多能放size-1个数据。)
因为这个Queue会同时被多个线程访问,需要考虑在这种情况下Queue如何工作。首先, Queue需要是线程安全的,可以用Java里的synchronized关键字来确保同时只有一个Thread在访问Queue.
我们还可以注意到当Queue为空的时候,get操作是无法进行的;当Queue为满的时候,put操作又是无法进行的。在多线程访问遇到这种情况时,一般希望执行操作的线程可以等待(block)直到该操作可以进行下去。比如,但一个Thread在一个空Queue上执行get方法的时候,这个 Thread应当等待(block),直到另外的Thread执行该Queue的put方法后,再继续执行下去。在Java里面,Object对象的 wait(),notify()方法提供了这样的功能。
*/
class SyncQueue {
protected Object[] array;
      protected int next;
      protected int oldest;
      protected int size;

       public SyncQueue(int size) {
         array = new Object[size];
         size = size;
  //oldest指向Queue中最老的数据所在的位置,next指向下一个可以放新数据的位置。
  oldest = 0;   //最后可以取走得线程的索引,就是刚刚取走的线程后边的那个线程。
  next = 0; //可以放入新线程的索引。就是刚刚放入的线程的索引的下一位
}
//向线程缓冲池中放入新的线程
//先判断缓冲池是否已经满了,如果满了则等待wait线程执行结束再放入
//涉及到wait和notify方法得都的是在同步synchronized方法里或者同步块里
public synchronized void put(Object o) {
  while (full()) {
   try {
    wait();
   } catch (InterruptedException ex) {
    throw new ExceptionAdapter(ex);
   }
  }
  //线程池未满,继续放入线程
  array[next] = o;
   next = (next + 1) % size;//计算下一个可放入线程的位置,对size求余是为了保证不超出数组范围。且可以循环使用。
  notify();//clinet放入线程后通知server取出线程去执行
}
//从缓冲池中取出线程 同步synchronized方法
//如果此时线程池为空,则等待放入线程,否则取出线程并通知client放入线程
public synchronized Object get() {
  while (empty()) {
   try {
    wait(); //等待放入线程
   } catch (InterruptedException ex) {
    throw new ExceptionAdapter(ex);
   }
  }
  Object ret = array[oldest];//获得最有一个线程
  oldest = (oldest + 1) % size;//更改下一个可取走线程的位置,对size求余是为了保证不超出数组范围,且可以循环使用。
  //server取走线程后 通知client放入线程
  notify();
  //返回最有一个线程对象去执行
  return ret;
}
//判断线程池是否是空的
protected boolean empty() {
//如果下一个可放入线程的位置就是最后一个可取走的线程的位置,则表示线程池是空的
  return next == oldest;
}
//判断线程池是否是满得
protected boolean full() {
  //如果下一个可放入线程的位置+1对线程池的大小取余等于最后一个可取走的线程得位置,表示线程池是满地。
  return (next + 1) % size == oldest;

}
}
/ *
next = (next + 1) % size就相当于:(oldest一样,保证不超过数组范围,又可以持续循环)
next ++;
//如果加到最大值,重新从0开始
if(next==size)
{
  next =0;
}
*/
/*
Thread缓冲池得原理:定义一个大小为size的Object数组,访队列方式添加和取出数据(先进先出),用next表示可以放入下一个线程的位置(如已经有了1 2 3,则next=4),用oldest表示下一个可以读取线程的位置(如 1234 已经把2取走,则下一个可以取走的oldest=3),client每放入一个新的线程之前,判断缓冲池是否已经满了,满了就等待(wait)
server取走线程执行,否则放入线程,并修改可以放入下一个线程的位置 (方法是next =(next+1)%size 对size求余保证不超过数组范围,又可以持续循环),然后通知(notify)server取走线程对象。
server每次读取一个线程之前, 先判断线程池是否是空的,空的就等待(wait)client放入线程,否则取走最先放入的那个线程(例如数组1 2 3 4,读取oldest=1的线程对象,此时可放入next=5 ), 然后修改可读取线程对象的位置(方法是oldest =(oldest+1)%size 对size求余保证不超过数组范围,又可以持续循环),最后通知(notify)client继续放入线程*/


2>>多线程编程
   随着计算机技术的发展,编程模型也越来越复杂多样化。但多线程编程模型是目前计算机系统架构的最终模型。随着CPU主频的不断攀升,X86架构的硬件已经成为瓶,在这种架构的CPU主频最高为4G。事实上目前3.6G主频的CPU已经接近了顶峰。   如果不能从根本上更新当前CPU的架构(在很长一段时间内还不太可能),那么继续 提高CPU性能的方法就是超线程CPU模式那么,作业系统、应用程序要发挥CPU的最大性能,就是要改变到以多线程编程模型为主的并行处理系统和并发式应用程序
   所以,掌握多线程编程模型,不仅是目前提高应用性能的手段,更是下一代编程模型的核心思想。多线程编程的目的,就是"最大限度地利用CPU资源",当某一线程的处理不需要占用CPU而只和I/O,OEMBIOS等资源打交道时,让需要占用CPU资源的其它线程有机会获得CPU资源。从根本上说,这就是多线程编程的最终目的。

2>>线程对象和线程的区别:  线程对象是可以产生线程的对象。比如在java平台中 Thread对象,Runnable对象
        线程,是指正在执行的一个指点令序列。在java平台上 是指从一个线程对象的start()开始,运行run方法体中的那一段相对独立的过程。在JAVA中,线程对象是JVM产生的一个普通的Object子类。而线程是CPU分配给这个对象的一个运行过程。我们说"个线程在干什么",不说"一个线程对象在干什么"

3>>JVM; Java Virtual Machine(Java虚拟机)。运行main方法:JVM进程被启动,在同一个JVM进程中,有且只有一个进程,就是它自己。然后在这个JVM环境中,所有程序的运行都是以线程来运行。JVM最先会产生一个主线程,由它来运行指定程序的入口点。在这个程序中,就是主线程从main方法开始运行。当main方法结束后,主线程运行完成。JVM进程也随之退出。(每个程序只有一个main方法,所以它只对应一个进程,但对应多个线程)

>>4多线程Java 应用程序构建(Concurrent Programming)
1 JSR-166(Java concurrency utilities),是Java5.0的一部分,通过着重在宽度并提供跨域大范围并发编程风格的重要功能,大大简化了在Java中并发应用程序的开发。
注意:start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。(和线程的时间片有关系).
>>随机数休眠进程:Thread.sleep((int) Math.random() * 10);

>>同步方法和方法调用的区别:
public synchronized void m1(){a =1000;}
public synchronized  void m2() {  a =5000;}
public void m3() {  a =5000;}
当m1执行时,m2无法进行,m3可以,因为m2的进行要对a进行加锁,但此时m1已经将a加锁,所以m2无法进行。而m3的进行无需对m3进行加锁,所以m3可以正常的进行。 也就是说:不是同步的方法可以访问正在同步的方法的变量资源
>>加锁的变量的使用机制(自己理解)
加锁的同步方法或者同步块,对方法体内的变量资源独占,当其他的方法访问变量时,需要等待该方法对变量资源解锁,也就是该方法结束,也就是方法运行到"}"(与数据库的修改操作需要同步,查询操作不用同步)

>>同步方法的执行过程特点
public synchronized void m2()
{
语句1;
语句2;
语句3;
语句4;
。。。
}
执行时,语句1 2 3 4不允许被别的线程打 断,即执行完1就走2,然后就走3,紧接著4

网上资源:
http://www.enet.com.cn/eschool/zhuanti/java/ (孙鑫)
http://v.youku.com/v_show/id_XNTMzMTY4MTI=.html (尚学堂)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值