创建新线程的常用方式:
1. 直接使用Thread创建
Thread thread = new Thread();
thread.start();
2. 扩展java.lang.Thread类
Thread类的定义public class Threadextends Object implements Runnable(){…}
扩展Thread类的实质其实也是实现Runnable接口,只不过Thread类继承了Object类方法
3. 实现Runnable接口
具体代码:
1. 扩展java.lang.Thread类
public class test3_4 extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MyThread myThread = new MyThread();
myThread.start();
}
class MyThread extends Thread{
public void run() {
System.out.println("zz");
}
}
}
注:看见网上有人举这个例子
MyThread myThread = new MyThread();
myThread.start();
myThread.start();
myThread.start();
我在模拟器上测试了运行不过,不能得到预期结果。不知道为什么!runnable的也不行!
2. 实现Runnable接口
public class test3_4 extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MyThread myThread = new MyThread();
new Thread(myThread).start();
}
class MyThread implements Runnable{
public void run() {
System.out.println("zz");
}
}
}
或者
public class test3_4 extends Activity implements OnClickListener, Runnable{
private Button button;
private TextView text;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button)findViewById(R.id.button);
text = (TextView)findViewById(R.id.text);
button.setOnClickListener(this);
}
public void onClick(View v) {
Thread thread = new Thread(this);
thread.start();
}
public void run() {
System.out.println("zz");
}
}
经典实例:
多个窗口一起卖火车票问题。假设有3个窗口同时售票,共有10张火车票代售。启动三个线程卖共同的10张票。
1. 使用下面的代码试图实现功能
public class test3_5 extends Activity implements OnClickListener{
private Button button;
private TextView text;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button)findViewById(R.id.button);
text = (TextView)findViewById(R.id.text);
button.setOnClickListener(this);
}
public void onClick(View v) {
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--);
}
}
}
}
}
运行结果:
05-11 08:24:09.426: INFO/System.out(6331): Thread-8==>10
05-11 08:24:09.457: INFO/System.out(6331): Thread-8==>9
05-11 08:24:09.526: INFO/System.out(6331): Thread-8==>8
05-11 08:24:09.548: INFO/System.out(6331): Thread-8==>7
05-11 08:24:09.556: INFO/System.out(6331): Thread-8==>6
05-11 08:24:09.556: INFO/System.out(6331): Thread-8==>5
05-11 08:24:09.576: INFO/System.out(6331): Thread-8==>4
05-11 08:24:09.597: INFO/System.out(6331): Thread-10==>10
05-11 08:24:09.606: INFO/System.out(6331): Thread-10==>9
05-11 08:24:09.606: INFO/System.out(6331): Thread-10==>8
05-11 08:24:09.648: INFO/System.out(6331): Thread-8==>3
05-11 08:24:09.656: INFO/System.out(6331): Thread-9==>10
05-11 08:24:09.656: INFO/System.out(6331): Thread-9==>9
05-11 08:24:09.666: INFO/System.out(6331): Thread-8==>2
05-11 08:24:09.666: INFO/System.out(6331): Thread-8==>1
05-11 08:24:09.686: INFO/System.out(6331): Thread-9==>8
05-11 08:24:09.686: INFO/System.out(6331): Thread-10==>7
05-11 08:24:09.686: INFO/System.out(6331): Thread-10==>6
05-11 08:24:09.737: INFO/System.out(6331): Thread-9==>7
05-11 08:24:09.746: INFO/System.out(6331): Thread-9==>6
05-11 08:24:09.746: INFO/System.out(6331): Thread-9==>5
05-11 08:24:09.766: INFO/System.out(6331): Thread-10==>5
05-11 08:24:09.776: INFO/System.out(6331): Thread-10==>4
05-11 08:24:09.776: INFO/System.out(6331): Thread-10==>3
05-11 08:24:09.776: INFO/System.out(6331): Thread-10==>2
05-11 08:24:09.846: INFO/System.out(6331): Thread-9==>4
05-11 08:24:09.846: INFO/System.out(6331): Thread-9==>3
05-11 08:24:09.846: INFO/System.out(6331): Thread-9==>2
05-11 08:24:09.886: INFO/System.out(6331): Thread-9==>1
05-11 08:24:09.886: INFO/System.out(6331): Thread-10==>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();
}
运行结果:
05-11 08:41:50.946: INFO/System.out(6790): 窗口2==>10
05-11 08:41:50.956: INFO/System.out(6790): 窗口2==>8
05-11 08:41:50.986: INFO/System.out(6790): 窗口1==>9
05-11 08:41:50.996: INFO/System.out(6790): 窗口1==>5
05-11 08:41:51.006: INFO/System.out(6790): 窗口1==>4
05-11 08:41:51.018: INFO/System.out(6790): 窗口2==>6
05-11 08:41:51.018: INFO/System.out(6790): 窗口2==>3
05-11 08:41:51.026: INFO/System.out(6790): 窗口2==>2
05-11 08:41:51.036: INFO/System.out(6790): 窗口1==>1
05-11 08:41:51.046: INFO/System.out(6790): 窗口3==>7
分析:
我认为此处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~
5. 使用实现Runnable接口的方法重新实现上述功能
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 implements Runnable{
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--);
}
}
关于线程的理解个人推荐一篇非常棒的文章,里面对java线程进行的详细的总结,仔细阅读必有收获!
[url]http://lavasoft.blog.51cto.com/62575/27069/
[/url]
1. 直接使用Thread创建
Thread thread = new Thread();
thread.start();
2. 扩展java.lang.Thread类
Thread类的定义public class Threadextends Object implements Runnable(){…}
扩展Thread类的实质其实也是实现Runnable接口,只不过Thread类继承了Object类方法
3. 实现Runnable接口
具体代码:
1. 扩展java.lang.Thread类
public class test3_4 extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MyThread myThread = new MyThread();
myThread.start();
}
class MyThread extends Thread{
public void run() {
System.out.println("zz");
}
}
}
注:看见网上有人举这个例子
MyThread myThread = new MyThread();
myThread.start();
myThread.start();
myThread.start();
我在模拟器上测试了运行不过,不能得到预期结果。不知道为什么!runnable的也不行!
2. 实现Runnable接口
public class test3_4 extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MyThread myThread = new MyThread();
new Thread(myThread).start();
}
class MyThread implements Runnable{
public void run() {
System.out.println("zz");
}
}
}
或者
public class test3_4 extends Activity implements OnClickListener, Runnable{
private Button button;
private TextView text;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button)findViewById(R.id.button);
text = (TextView)findViewById(R.id.text);
button.setOnClickListener(this);
}
public void onClick(View v) {
Thread thread = new Thread(this);
thread.start();
}
public void run() {
System.out.println("zz");
}
}
经典实例:
多个窗口一起卖火车票问题。假设有3个窗口同时售票,共有10张火车票代售。启动三个线程卖共同的10张票。
1. 使用下面的代码试图实现功能
public class test3_5 extends Activity implements OnClickListener{
private Button button;
private TextView text;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button)findViewById(R.id.button);
text = (TextView)findViewById(R.id.text);
button.setOnClickListener(this);
}
public void onClick(View v) {
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--);
}
}
}
}
}
运行结果:
05-11 08:24:09.426: INFO/System.out(6331): Thread-8==>10
05-11 08:24:09.457: INFO/System.out(6331): Thread-8==>9
05-11 08:24:09.526: INFO/System.out(6331): Thread-8==>8
05-11 08:24:09.548: INFO/System.out(6331): Thread-8==>7
05-11 08:24:09.556: INFO/System.out(6331): Thread-8==>6
05-11 08:24:09.556: INFO/System.out(6331): Thread-8==>5
05-11 08:24:09.576: INFO/System.out(6331): Thread-8==>4
05-11 08:24:09.597: INFO/System.out(6331): Thread-10==>10
05-11 08:24:09.606: INFO/System.out(6331): Thread-10==>9
05-11 08:24:09.606: INFO/System.out(6331): Thread-10==>8
05-11 08:24:09.648: INFO/System.out(6331): Thread-8==>3
05-11 08:24:09.656: INFO/System.out(6331): Thread-9==>10
05-11 08:24:09.656: INFO/System.out(6331): Thread-9==>9
05-11 08:24:09.666: INFO/System.out(6331): Thread-8==>2
05-11 08:24:09.666: INFO/System.out(6331): Thread-8==>1
05-11 08:24:09.686: INFO/System.out(6331): Thread-9==>8
05-11 08:24:09.686: INFO/System.out(6331): Thread-10==>7
05-11 08:24:09.686: INFO/System.out(6331): Thread-10==>6
05-11 08:24:09.737: INFO/System.out(6331): Thread-9==>7
05-11 08:24:09.746: INFO/System.out(6331): Thread-9==>6
05-11 08:24:09.746: INFO/System.out(6331): Thread-9==>5
05-11 08:24:09.766: INFO/System.out(6331): Thread-10==>5
05-11 08:24:09.776: INFO/System.out(6331): Thread-10==>4
05-11 08:24:09.776: INFO/System.out(6331): Thread-10==>3
05-11 08:24:09.776: INFO/System.out(6331): Thread-10==>2
05-11 08:24:09.846: INFO/System.out(6331): Thread-9==>4
05-11 08:24:09.846: INFO/System.out(6331): Thread-9==>3
05-11 08:24:09.846: INFO/System.out(6331): Thread-9==>2
05-11 08:24:09.886: INFO/System.out(6331): Thread-9==>1
05-11 08:24:09.886: INFO/System.out(6331): Thread-10==>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();
}
运行结果:
05-11 08:41:50.946: INFO/System.out(6790): 窗口2==>10
05-11 08:41:50.956: INFO/System.out(6790): 窗口2==>8
05-11 08:41:50.986: INFO/System.out(6790): 窗口1==>9
05-11 08:41:50.996: INFO/System.out(6790): 窗口1==>5
05-11 08:41:51.006: INFO/System.out(6790): 窗口1==>4
05-11 08:41:51.018: INFO/System.out(6790): 窗口2==>6
05-11 08:41:51.018: INFO/System.out(6790): 窗口2==>3
05-11 08:41:51.026: INFO/System.out(6790): 窗口2==>2
05-11 08:41:51.036: INFO/System.out(6790): 窗口1==>1
05-11 08:41:51.046: INFO/System.out(6790): 窗口3==>7
分析:
我认为此处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~
5. 使用实现Runnable接口的方法重新实现上述功能
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 implements Runnable{
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--);
}
}
关于线程的理解个人推荐一篇非常棒的文章,里面对java线程进行的详细的总结,仔细阅读必有收获!
[url]http://lavasoft.blog.51cto.com/62575/27069/
[/url]