本文转载自http://blog.csdn.net/z496844387/article/details/6412507


创建线程的方法:

官网的说法:

There are basically two main ways of having a Thread execute application code. One is providing a new class that extends Thread and overriding its run() method. The other is providing a new Thread instance with a Runnable object during its creation. In both cases, the start() method must be called to actually execute the new Thread.

扩展Thread的示例代码:

public class CommonTestActivity extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                new Thread(){        public void run(){        System.out.println("Thread is running.");        }        }.start();    }}

使用Runnable的示例代码:

public class CommonTestActivity extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                new Thread(r).start();    }        Runnable r = new Runnable() {        @Override        public void run() {                    System.out.println("Runnable running ");        }    };    }

经典实例:

多个窗口一起卖火车票问题。假设有3个窗口同时售票,共有10张火车票代售。启动三个线程卖共同的10张票。

1. 使用下面的代码试图实现功能

public class CommonTestActivity extends Activity{private Button mybutton;private TextView mytext;protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);mybutton = (Button) findViewById(R.id.button);mytext = (TextView) findViewById(R.id.text);        mybutton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stub        MyThread myThread1 = new MyThread();         MyThread myThread2= new MyThread();         MyThread myThread3 = new MyThread();         myThread1.start();         myThread2.start();         myThread3.start(); }        });       }class MyThread extends Thread {private int tickets = 10;public void run() {for (int i = 0; i < 200; i++) {if (tickets > 0) {System.out.println(Thread.currentThread().getName() + "==>"+ tickets--);}}}}}
输出如下

11-17 22:45:01.234: I/System.out(672): Thread-10==>1011-17 22:45:01.234: I/System.out(672): Thread-10==>911-17 22:45:01.234: I/System.out(672): Thread-10==>811-17 22:45:01.234: I/System.out(672): Thread-10==>711-17 22:45:01.234: I/System.out(672): Thread-10==>611-17 22:45:01.234: I/System.out(672): Thread-10==>511-17 22:45:01.234: I/System.out(672): Thread-10==>411-17 22:45:01.234: I/System.out(672): Thread-10==>311-17 22:45:01.244: I/System.out(672): Thread-10==>211-17 22:45:01.244: I/System.out(672): Thread-10==>111-17 22:45:01.244: I/System.out(672): Thread-11==>1011-17 22:45:01.244: I/System.out(672): Thread-11==>911-17 22:45:01.244: I/System.out(672): Thread-11==>811-17 22:45:01.244: I/System.out(672): Thread-11==>711-17 22:45:01.244: I/System.out(672): Thread-11==>611-17 22:45:01.254: I/System.out(672): Thread-11==>511-17 22:45:01.254: I/System.out(672): Thread-11==>411-17 22:45:01.254: I/System.out(672): Thread-11==>311-17 22:45:01.254: I/System.out(672): Thread-11==>211-17 22:45:01.254: I/System.out(672): Thread-11==>111-17 22:45:01.264: I/System.out(672): Thread-12==>1011-17 22:45:01.264: I/System.out(672): Thread-12==>911-17 22:45:01.264: I/System.out(672): Thread-12==>811-17 22:45:01.264: I/System.out(672): Thread-12==>711-17 22:45:01.264: I/System.out(672): Thread-12==>611-17 22:45:01.274: I/System.out(672): Thread-12==>511-17 22:45:01.274: I/System.out(672): Thread-12==>411-17 22:45:01.274: I/System.out(672): Thread-12==>311-17 22:45:01.274: I/System.out(672): Thread-12==>211-17 22:45:01.274: I/System.out(672): Thread-12==>1

分析:

运行结果与预期不一致,分析可以看出3个线程各种卖各自的10张票,而不是共同的10张票。

在上面的代码中,只能保证:每个线程都将启动,每个线程都将运行直到完成。一系列线程以某种顺序启动并不意味着将按该顺序执行。对于任何一组启动的线程来说,调度程序不能保证其执行次序,持续时间也无法保证。


2. 只修改onClick里面的代码,并分析运行结果

public void onClick(View v) {     //实例化线程对象     MyThread myThread = new MyThread();     new Thread(myThread, "窗口1").start();     new Thread(myThread, "窗口2").start();     new Thread(myThread, "窗口3").start(); }

输出如下

11-17 22:49:17.314: I/System.out(708): 窗口1==>1011-17 22:49:17.314: I/System.out(708): 窗口1==>911-17 22:49:17.314: I/System.out(708): 窗口1==>811-17 22:49:17.314: I/System.out(708): 窗口1==>711-17 22:49:17.314: I/System.out(708): 窗口1==>611-17 22:49:17.324: I/System.out(708): 窗口1==>511-17 22:49:17.324: I/System.out(708): 窗口1==>411-17 22:49:17.324: I/System.out(708): 窗口1==>311-17 22:49:17.324: I/System.out(708): 窗口1==>211-17 22:49:17.324: I/System.out(708): 窗口1==>1

分析:

我认为此处3个窗口已经是在卖共同的10张票了,只不过由于没有进行线程同步才造成数据混乱。

线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。

3. 下面继续修改代码,验证我刚得猜测。

public void onClick(View v) {
//实例化线程对象
MyThread myThread = new MyThread();
new Thread(myThread, "窗口1").start();
new Thread(myThread, "窗口2").start();
new Thread(myThread, "窗口3").start();
}

class MyThread extends Thread{
private int tickets = 10;
public void run() {
for(int i = 0; i< 200; i++){
sell();
}
}
public synchronized void sell(){
if(tickets > 0)
{
System.out.println(Thread.currentThread().getName() + "==>" + tickets--);
}
}
}

运行结果:

05-11 08:53:31.986: INFO/System.out(7116): 窗口1==>10
05-11 08:53:32.006: INFO/System.out(7116): 窗口1==>9
05-11 08:53:32.016: INFO/System.out(7116): 窗口1==>8
05-11 08:53:32.066: INFO/System.out(7116): 窗口1==>7
05-11 08:53:32.086: INFO/System.out(7116): 窗口1==>6
05-11 08:53:32.106: INFO/System.out(7116): 窗口1==>5
05-11 08:53:32.106: INFO/System.out(7116): 窗口1==>4
05-11 08:53:32.126: INFO/System.out(7116): 窗口1==>3
05-11 08:53:32.146: INFO/System.out(7116): 窗口1==>2
05-11 08:53:32.146: INFO/System.out(7116): 窗口1==>1

分析:

一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。

释放锁是指持锁线程退出了synchronized同步方法或代码块。

上述代码没有Thread.sleep(10),换句话说线程一一直处于运行状态,没有释放锁,没有给其他线程运行的机会。

4. 根据上述分析,修改代码如下:

public void onClick(View v) {
//实例化线程对象
MyThread myThread = new MyThread();
new Thread(myThread, "窗口1").start();
new Thread(myThread, "窗口2").start();
new Thread(myThread, "窗口3").start();
}
class MyThread extends Thread{
private int tickets = 10;
public void run() {
for(int i = 0; i< 200; i++){
try{
sell();
Thread.sleep(10);
}catch (InterruptedException e) {
System.out.println("我被打断了" + Thread.currentThread().getName());
e.printStackTrace();
}

}
}
public synchronized void sell(){
if(tickets > 0)
{
System.out.println(Thread.currentThread().getName() + "==>" + tickets--);
}
}
}

运行结果:

05-11 09:17:07.496: INFO/System.out(7898): 窗口1==>10
05-11 09:17:07.528: INFO/System.out(7898): 窗口1==>9
05-11 09:17:07.546: INFO/System.out(7898): 窗口1==>8
05-11 09:17:07.577: INFO/System.out(7898): 窗口1==>7
05-11 09:17:07.626: INFO/System.out(7898): 窗口3==>6
05-11 09:17:07.626: INFO/System.out(7898): 窗口2==>5
05-11 09:17:07.636: INFO/System.out(7898): 窗口1==>4
05-11 09:17:07.646: INFO/System.out(7898): 窗口2==>3
05-11 09:17:07.646: INFO/System.out(7898): 窗口1==>2
05-11 09:17:07.656: INFO/System.out(7898): 窗口3==>1

分析:

此次得出的正是我们想要的结果!O(∩_∩)O~


更多相关文章

  1. 代码获取Android的VersionCode和VersionName信息
  2. Android加载Gif动画实现代码
  3. android一些核心功能程序代码
  4. android 根据SD卡中图片路径读取并显示SD中的图片――源代码
  5. Android 获取屏幕尺寸实例代码
  6. Android下MP3播放器的实现源代码01
  7. android多线程进度条
  8. android开源代码站开通啦!
  9. Android 闪关灯代码

随机推荐

  1. SQL中带闭包表的有向循环图
  2. CentOS下mysql启动失败
  3. Sqlserver 链接服务器和同义词
  4. Python SQLITE数据库操作简便易用 (转)
  5. PHP“智能”搜索引擎搜索Mysql表的建议
  6. 关于NavicatPremium导入CSV文件乱码的问
  7. 查询表中的某一行,表中没有行号相关的属性
  8. 在VS下用C语言连接SQLServer2008
  9. 基于GUI和SQL的剧院票务管理系统
  10. mysql5.6和5.7的权限密码设置