java something

不要以为......很遥远
随笔 - 23, 文章 - 1, 评论 - 2, 引用 - 0
数据加载中……

2011年8月23日

Activity生命周期

现有两个Activity:  Activity1,Activity2

先启动Activity1运行顺序为: Activity1 onCreate -> Activity1 onStart -> Activity1 onResume
用Intent从Activity1跳到Activity2运行顺序 : 
Activity1 onPause -> Activity2 onCreate -> Activity2 onStart -> Activity2 onResume ->Activity1 onStop -> Activity1  onDestroy
退出应用程序: Activity2 onResume ->Activity2 onStop -> Activity2  onDestroy

posted @ 2011-09-02 17:48 Jamie 阅读(216) | 评论 (0)编辑 收藏

控制3个线程运行顺序的Demo

本程序可以控制3个线程按顺序执行, 代码如下:

public class Test3 {

 public static void main(String[] args) throws IOException {
  final Test obj = new Test();
  
  new Thread()
  {
   public void run()
   {
    obj.m1();
   }
  }.start();
  new Thread()
  {
   public void run()
   {
    obj.m2();
   }
  }.start();
  new Thread()
  {
   public void run()
   {
    obj.m3();
   }
  }.start();
  
 }

}

class Test
{
 static int count;
 volatile int target = 1;
 synchronized void m1()
 { 
   for (int i = 0; i < 10; i++)
   {
    while (target == 2 || target == 3)
    {
     try {
      wait();
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
    System.out.println("m1() =" + i);
    target = 2;
    notifyAll();
   }
 }
 
 synchronized void m2()
 {
  for (int i = 0; i < 10; i++)
  {
   while (target == 1 || target == 3)
   {
    try {
     wait();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   System.out.println("m2() =" + i);
   target = 3;
   notifyAll();
  }
 }
 
 synchronized void m3()
 {
  for (int i = 0; i < 10; i++)
  {
   while (target == 1 || target == 2)
   {
    try {
     wait();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   System.out.println("m3() =" + i);
   target = 1;
   notifyAll();
  }
 }
}

posted @ 2011-09-02 02:27 Jamie 阅读(1759) | 评论 (2)编辑 收藏

线程的同步与共享

     摘要: 线程的同步与共享 前面程序中的线程都是独立的、异步执行的线程。但在很多情况下,多个线程需要共享数据资源,这就涉及到线程的同步与资源共享的问题。 1 资源冲突 下面的例子说明,多个线程共享资源,如果不加以控制可能会产生冲突。 程序CounterTest.java   Code highlighting produced by Actipro CodeHighlight...  阅读全文

posted @ 2011-09-02 01:38 Jamie 阅读(470) | 评论 (0)编辑 收藏

线程的状态与调度

  1,线程的生命周期

        线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。



    1.新建状态(New): 
        当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码

     2.就绪状态(Runnable)

        一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。

        处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。

    3.运行状态(Running)

        当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.

    
4. 阻塞状态(Blocked)

        线程运行过程中,可能由于各种原因进入阻塞状态:
        1>线程通过调用sleep方法进入睡眠状态;
        2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
        3>线程试图得到一个锁,而该锁正被其他线程持有;
        4>线程在等待某个触发条件;
        ......           

        所谓阻塞状态是正在运行的线程没有运行结束,暂时让出
CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。

    5. 死亡状态(Dead)

        有两个原因会导致线程死亡:
        1) run方法正常退出而自然死亡,
        2) 一个未捕获的异常终止了run方法而使线程猝死。
        为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.




2,  线程的优先级和调度

Java的每个线程都有一个优先级,当有多个线程处于就绪状态时,线程调度程序根据线程的优先级调度线程运行。

可以用下面方法设置和返回线程的优先级。

    · public final void setPriority(int newPriority) 设置线程的优先级。

    · public final int getPriority() 返回线程的优先级。

newPriority为线程的优先级,其取值为110之间的整数,也可以使用Thread类定义的常量来设置线程的优先级,这些常量分别为:Thread.MIN_PRIORITYThread.NORM_PRIORITYThread.MAX_PRIORITY,它们分别对应于线程优先级的1510,数值越大优先级越高。当创建Java线程时,如果没有指定它的优先级,则它从创建该线程那里继承优先级。

一般来说,只有在当前线程停止或由于某种原因被阻塞,较低优先级的线程才有机会运行。

前面说过多个线程可并发运行,然而实际上并不总是这样。由于很多计算机都是单CPU的,所以一个时刻只能有一个线程运行,多个线程的并发运行只是幻觉。在单CPU机器上多个线程的执行是按照某种顺序执行的,这称为线程的调度(scheduling)

大多数计算机仅有一个CPU,所以线程必须与其他线程共享CPU。多个线程在单个CPU是按照某种顺序执行的。实际的调度策略随系统的不同而不同,通常线程调度可以采用两种策略调度处于就绪状态的线程。

(1) 抢占式调度策略

     Java运行时系统的线程调度算法是抢占式的 (preemptive)Java运行时系统支持一种简单的固定优先级的调度算法。如果一个优先级比其他任何处于可运行状态的线程都高的线程进入就绪状态,那么运行时系统就会选择该线程运行。新的优先级较高的线程抢占(preempt)了其他线程。但是Java运行时系统并不抢占同优先级的线程。换句话说,Java运行时系统不是分时的(time-slice)。然而,基于Java Thread类的实现系统可能是支持分时的,因此编写代码时不要依赖分时。当系统中的处于就绪状态的线程都具有相同优先级时,线程调度程序采用一种简单的、非抢占式的轮转的调度顺序。

(2) 时间片轮转调度策略

    有些系统的线程调度采用时间片轮转(round-robin)调度策略。这种调度策略是从所有处于就绪状态的线程中选择优先级最高的线程分配一定的CPU时间运行。该时间过后再选择其他线程运行。只有当线程运行结束、放弃(yield)CPU或由于某种原因进入阻塞状态,低优先级的线程才有机会执行。如果有两个优先级相同的线程都在等待CPU,则调度程序以轮转的方式选择运行的线程。

 3.  线程状态的改变

一个线程在其生命周期中可以从一种状态改变到另一种状态,线程状态的变迁如图所示:

    
    
1>  控制线程的启动和结束

当一个新建的线程调用它的start()方法后即进入就绪状态,处于就绪状态的线程被线程调度程序选中就可以获得CPU时间,进入运行状态,该线程就开始运行run()方法。

控制线程的结束稍微复杂一点。如果线程的run()方法是一个确定次数的循环,则循环结束后,线程运行就结束了,线程对象即进入死亡状态。如果run()方法是一个不确定循环,早期的方法是调用线程对象的stop()方法,然而由于该方法可能导致线程死锁,因此从1.1版开始,不推荐使用该方法结束线程。一般是通过设置一个标志变量,在程序中改变标志变量的值实现结束线程。请看下面的例子:

程序 ThreadStop.java

import java.util.*;

class Timer implements Runnable{

    
boolean flag=true;
    
public void run(){
      
while(flag){
        System.out.print(
"\r\t"+new Date()+"");
        
try{
              Thread.sleep(
1000);
        }
catch(InterruptedException e){} 
      }
      System.out.println(
"\n"+Thread.currentThread().getName()+" Stop");
    }

    
public void stopRun(){
           flag 
= false;
    }
}

public class ThreadStop{
    
public static void main(String args[]){
       Timer timer 
= new Timer();
       Thread thread 
= new Thread(timer);       
       thread.setName(
"Timer");
       thread.start();

       
for(int i=0;i<100;i++){
         System.out.print(
"\r"+i);
        
try{
              Thread.sleep(
100);
        }
catch(InterruptedException e){} 
       }     
       timer.stopRun();
    }
}

该程序在Timer类中定义了一个布尔变量flag,同时定义了一个stopRun()方法,在其中将该变量设置为false。在主程序中通过调用该方法,从而改变该变量的值,使得run()方法的while循环条件不满足,从而实现结束线程的运行。

说明  Thread类中除了stop()方法被标注为不推荐(deprecated) 使用外,suspend()方法和resume()方法也被标明不推荐使用,这两个方法原来用作线程的挂起和恢复.

2>  线程阻塞条件

处于运行状态的线程除了可以进入死亡状态外,还可能进入就绪状态和阻塞状态。下面分别讨论这两种情况:

(1) 运行状态到就绪状态

处于运行状态的线程如果调用了yield()方法,那么它将放弃CPU时间,使当前正在运行的线程进入就绪状态。这时有几种可能的情况:如果没有其他的线程处于就绪状态等待运行,该线程会立即继续运行;如果有等待的线程,此时线程回到就绪状态状态与其他线程竞争CPU时间,当有比该线程优先级高的线程时,高优先级的线程进入运行状态,当没有比该线程优先级高的线程时,但有同优先级的线程,则由线程调度程序来决定哪个线程进入运行状态,因此线程调用yield()方法只能将CPU时间让给具有同优先级的或高优先级的线程而不能让给低优先级的线程。

一般来说,在调用线程的yield()方法可以使耗时的线程暂停执行一段时间,使其他线程有执行的机会。

(2) 运行状态到阻塞状态

有多种原因可使当前运行的线程进入阻塞状态,进入阻塞状态的线程当相应的事件结束或条件满足时进入就绪状态。使线程进入阻塞状态可能有多种原因:

线程调用了sleep()方法,线程进入睡眠状态,此时该线程停止执行一段时间。当时间到时该线程回到就绪状态,与其他线程竞争CPU时间。

Thread类中定义了一个interrupt()方法。一个处于睡眠中的线程若调用了interrupt()方法,该线程立即结束睡眠进入就绪状态。

如果一个线程的运行需要进行I/O操作,比如从键盘接收数据,这时程序可能需要等待用户的输入,这时如果该线程一直占用CPU,其他线程就得不到运行。这种情况称为I/O阻塞。这时该线程就会离开运行状态而进入阻塞状态。Java语言的所有I/O方法都具有这种行为。

③ 有时要求当前线程的执行在另一个线程执行结束后再继续执行,这时可以调用join()方法实现,join()方法有下面三种格式:

·         public void join() throws InterruptedException 使当前线程暂停执行,等待调用该方法的线程结束后再执行当前线程。

·         public void join(long millis) throws InterruptedException 最多等待millis毫秒后,当前线程继续执行。

·         public void join(long millis, int nanos) throws InterruptedException 可以指定多少毫秒、多少纳秒后继续执行当前线程。

上述方法使当前线程暂停执行,进入阻塞状态,当调用线程结束或指定的时间过后,当前线程线程进入就绪状态,例如执行下面代码:

t.join();

将使当前线程进入阻塞状态,当线程t执行结束后,当前线程才能继续执行。

④ 线程调用了wait()方法,等待某个条件变量,此时该线程进入阻塞状态。直到被通知(调用了notify()notifyAll()方法)结束等待后,线程回到就绪状态。

另外如果线程不能获得对象锁,也进入就绪状态。

后两种情况在下一节讨论。



















posted @ 2011-09-01 21:43 Jamie 阅读(3990) | 评论 (0)编辑 收藏

复习下java多线程

好久没搞这个了,今天把以前的笔记整理下,当复习。

Thread类和Runnable接口

多线程是一个程序中可以有多段代码同时运行,那么这些代码写在哪里,如何创建线程对象呢?

    首先,我们来看Java语言实现多线程编程的类和接口。在java.lang包中定义了Runnable接口和Thread类。

 

Runnable接口中只定义了一个方法:

·         public abstract void run()

这个方法要由实现了Runnable接口的类实现。Runnable对象称为可运行对象,一个线程的运行就是执行该对象的run()方法。


      Thread
类实现了Runnable接口,因此Thread对象也是可运行对象。同时Thread类也是线程类,该类的常用构造方法如下:

·         public Thread()

·         public Thread(Runnable target)

·         public Thread(String name)

·         public Thread(Runnable target, String name)
target为线程运行的目标对象,即线程调用start()方法启动后运行那个对象的run()方法,该对象的类型为Runnable,若没有指定目标对象,则以当前类对象为目标对象,name为线程名


 

  线程的创建 

介绍下如何创建和运行线程的两种方法。线程运行的代码就是实现了Runnable接口的类的run()方法或者是Thread类的子类的run()方法,因此构造线程体就有两种方法:
    ·         继承Thread类并覆盖它的run()方法;
    ·        
实现Runnable接口并实现它的run()方法。

  1,继承Thread类创建线程

通过继承Thread类,并覆盖run()方法,这时就可以用该类的实例作为线程的目标对象。下面的程序定义了SimpleThread类,它继承了Thread类并覆盖了run()方法。

程序SimpleThread.java

public class SimpleThread extends Thread{

  public SimpleThread(String str){

    super(str);

}

public void run(){

    for(int i=0; i<100; i++){

      System.out.println(getName()+" = "+ i);

      try{

         sleep((int)(Math.random()*100));

      }catch(InterruptedException e){}

    }

System.out.println(getName()+ " DONE");

}

}

_____________________________________________________________________________

    SimpleThread类继承了Thread类,并覆盖了run()方法,该方法就是线程体。

程序 ThreadTest.java

public class ThreadTest{

  public static void main(String args[]){

    Thread t1 = new SimpleThread("Runner A");

    Thread t2 = new SimpleThread("Runner B");

    t1.start();

    t2.start();

 }

}

_____________________________________________________________________________

ThreadTest类的main()方法中创建了两个SimpleThread类的线程对象并调用线程类的start()方法启动线程。构造线程时没有指定目标对象,所以线程启动后执行本类的run()方法。

注意,实际上ThreadTest程序中有三个线程同时运行,在应用程序的main()方法启动时,JVM就创建一个主线程,在主线程中可以创建其他线程。

  2,实现Runnable接口创建线程

可以定义一个类实现Runnable接口,然后将该类对象作为线程的目标对象。实现Runnable接口就是实现run()方法。

下面程序通过实现Runnable接口构造线程体。

程序 ThreadTest.java

class T1 implements Runnable{

  public void run(){

    for(int i=0;i<15;i++)

      System.out.println("Runner A="+i);

  }

}

class T2 implements Runnable{

  public void run(){

    for(int j=0;j<15;j++)

      System.out.println("Runner B="+j);

  }

}

public class ThreadTest{

  public static void main(String args[]){

    Thread t1=new Thread(new T1(),"Thread A");

    Thread t2=new Thread(new T2(),"Thread B");

    t1.start();

    t2.start();

  }

}

_____________________________________________________________________________




    

 



posted @ 2011-09-01 20:46 Jamie 阅读(375) | 评论 (0)编辑 收藏

android 项目下文件的作用

1, R.java 是建立项目时自动生成的,只读,用来定义该项目所有资源的索引文件。
这里面定义了很多常量, 名字与res文件夹的文件名和String.xml里的定义的常量名相同。当项目中加入了新的资源时,只需要刷新一下该项目,R.java 便自动生成了。
2, strings.xml 里面定义了字符串资源。 
    在类中可通过如下方式使用这些资源, Resource r = this.getContext().getResources(); String str = ((String) r.getString(R.string.name));
    在main.xml中可以 android:text="@string/name"
3,  mail.xml 用来写UI(布局,控件...)
    主程序继承Activity类,重写了void onCreate(Bundle savedInstanceState)方法。 在方法里通过setContentView(R.layout.main)设置Activity要显示的布局文件(\layout\main.xml)
4.  AndroidManifest.xml
    看下默认的:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">   //应用程序的名字
        <activity android:name=".WuActivity"   //默认启动哪个Activity
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

posted @ 2011-08-24 02:33 Jamie 阅读(1018) | 评论 (0)编辑 收藏

关于ADT和SDK版本

用最新的就都用最新的, 不然有可能导致配置过程中出现一些问题。

我用SDK3.2和ADT 0.9.5配置, 结果Preferences->Android里设置路径出现问题。

posted @ 2011-08-23 17:45 Jamie 阅读(244) | 评论 (0)编辑 收藏