传统线程

来源:互联网 发布:淘宝小号批量死的原因 编辑:程序博客网 时间:2024/04/29 14:26

      在计算机系统中有多个并发执行的程序,"程序"这个静态的概念已经不能描述程序动态变化的过程,所以引入了"进程".进程是程序的一次执行,进程由3大部分组成,程序、数据、进程控制块,传统的进程有两个基本的属性,可拥有资源的独立单位,可独立调度和分配的基本单位。由于频繁创建进程等一系列操作,时空开销很大,这就限制了并发程序的提高,所以就引入了线程,将进程中的两个基本属性分开,线程作为独立调度和分配的基本单位,进程作为独立分配资源的单位。线程和进程很相似,线程被称为轻量进程,进程被称为重量进程。简单的说线程就是一条执行路径,多条执行路径也就是多线程了,值得注意的是多线程并不能提高程序的运行效率,反而会降低程序的运行效率,因为cpu只有一个,按照时间片轮转的调度算法可以得知,只不过cpu的运行速度对于人类来说很快感觉不到便会认为程序是同时执行的。所谓同时执行 其实是cpu逐一来为每一个进程服务。我们常常可以看到的多线程下载又是怎么回事呢?那是因为抢占了服务器的带宽了。

       线程是系统的资源,java对其进行了描述,java描述事物也就是用类啦。提供了一系列有关操作线程的方法,

这个类就是:

java.lang
类 Thread

java.lang.Object  继承者 java.lang.Thread
所有已实现的接口:
Runnable

public class Thread
extends Object
implements Runnable
     1.线程的创建。
    new Thread().start();//开辟了一条新的执行路径。
    线程要运行的代码是放在run(){}方法中的。这个没有为什么。
    new Thread().start();//运行是没有反应。查看源码可以知道:
        public void run() {
if (target != null) {
   target.run();
}
     target是:private Runnable target;
     1).创建线程的方式一:
         继承Thread类覆盖run方法。
     2).将run()方法的代码封装到一个Runnable接口中。通过构造方法传递给线程。
        new Thread(new Runnable(){
                     run....
                   }).start();
     2.Runnable接口的思想。

     继承Thread创建线程是将线程和线程的任务绑定在一起,耦合度高,而通过Runnable接口将线程和线程的任务分开,更符合面向对      象的思想,实现了低耦合高内聚的设计思想。

     3.线程的5种状态,见下图:

  


线程的创建方式demo

<span style="font-size:18px;">public static void main(String[] args) {new Thread(new Runnable(){@Overridepublic void run() {while(true){System.out.println(Thread.currentThread().getName());}}}).start();new Thread(){public void run() {while(true){System.out.println(Thread.currentThread().getName());}};}.start();//运行那个run方法???//创建的是Thread的匿名子类对象并且覆盖了run方法,故运行的是子类的run方法。new Thread(new Runnable(){@Overridepublic void run() {while(true){System.out.println(Thread.currentThread().getName()+"runnable");}}}){public void run() {while(true){System.out.println(Thread.currentThread().getName()+"Thread sub");}};}.start();new Thread(){@Overridepublic void run() {};}.start();}</span>

 3.线程的同步互斥与通信。

  1)同步互斥:

    由于cpu是随机切换的, 在多线程环境中,各个线程可以共享各类资源,但有一些资源一次只能提供给一个线程使用,称为这些资源     称为临界资源。例如卖票。有100张票,分4个窗口来卖,每一个窗口相当于一个线程。多线程访问共享数据会出现安全问题,需要       特别”处理“.

   

<span style="font-size:18px;">package com.hb;public class TraditionalSynchronizedTest {public static void main(String[] args) {    new TraditionalSynchronizedTest().init();   }public void init(){final Outputer output=new Outputer();new Thread(new Runnable(){@Overridepublic void run() {               while(true){               output.output("hbbb");               }}}).start();new Thread(new Runnable(){@Overridepublic void run() {     while(true){               output.output("china");               }}}).start();}class Outputer{private String xxx="";public void output(String name){int len =name.length();synchronized (xxx) {//锁是xxxfor(int i =0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}}public  synchronized void output2(String name){//锁是thisint len =name.length();for(int i =0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}}public static synchronized void output3(String name){//锁是当前字节码对象int len =name.length();for(int i =0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}}</span>

 2) 线程间的通信: 

  多个线程可以并发执行,每一个线程都以各自独立、不可预知的速度向前推进。但是需要在某个点上相互协调合作,例如:经典问       题生产者和消费者,生产者生产一个产品,消费者消费一个产品,由于cpu...,如果生产者没有生产出产品,消费者就必须等待      (wait),消费者没有消费产品,生产都也必须等待。这就涉及到了线程间的通信,方法有,wait()、notify()、notifyAll()。这些方法都是  定义在Object类中的,为什么?因为锁可以是任意对象,而玩线程间的通信时必须标明所属的锁,锁相当于定义了一个范围,例如:  this.notify(),是唤醒this这个锁上的任意一个线程,没有锁没得玩啊,所以这些方法也就被定义在Object类中了。

<span style="font-size:18px;">package com.hb;public class TraditionalThreadCommunication {/** *  * 面试题: * 子线程循环10次,主线程循环20次,接着又是子线程循环10次,主线程循环20次,如此重复50次。 */public static void main(String[] args) {final Business b=new Business();    new Thread(new Runnable(){@Overridepublic void run() {  for(int i =1;i<=50;i++){b.sub1(i);  }}}).start();for(int i=1;i<=50;i++){b.main(i);}}}//将需要同步的代码提取出来单独存在,这样可以提高代码的扩展性等。class Business{private boolean flag =true;public synchronized void sub1(int i){//如果不是我,那就等待,由于线程存在伪唤醒的情况,所以给整个while(),用if也是可以的,不过不建议。    while(!flag){    try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}    }for(int j =1;j<=10;j++){System.out.println("sub thread sequence of "+j+" ,loop of "+i);}flag=false;this.notify();}public synchronized  void main(int i ){    while(flag){    try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}for(int j =1;j<=20;j++){System.out.println("main thread sequence of "+j+" ,loop of "+i);}flag=true;this.notify();}}}</span>

4.传统定时器:

  故名思义....

 

<span style="font-size:18px;">package com.hb;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class TraditionalTimerTest {/** * @param args */public static void main(String[] args) {//   传统定时器// Timer(),是定时器。//   schedule(TimerTask ,x)调度//   TimerTask是任务// x ,时间,什么时候bombing?/*new Timer().schedule(new TimerTask() {@Overridepublic void run() {             System.out.println("bombing!");}}, 500);//固定频率炸,也就是连环炸。        new Timer().scheduleAtFixedRate(        new TimerTask() {@Overridepublic void run() {System.out.println("bombing!");}},        1000,        2000);*/               //2秒搞一下,4秒搞一下,再2秒搞一下,如此循环class MyTimerTask extends TimerTask{     int count =0;@Overridepublic void run() { System.out.println("bombing!");  count=(count+1)%2; 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) {// TODO Auto-generated catch blocke.printStackTrace();}}}}</span>














 

0 0
原创粉丝点击