Android 学习系列 - Java 多线程
Java 多线程
Thread
sample
class MyThread extends Thread {
private String name;public MyThread(String name) { this.name = name;}@Overridepublic void run() { //.....}
}
class Main {
public static void main(String[] args) {
MyThread a = new MyThread('A');
MyThread b = new MyThread('B');
a.start();
b.start();
}
}
start 方法不能重复调用, 重复调用会出现java.lang.IllegalThreadStateException异常
Runnable
sample
class MyRunnable extend Runnable{
public MyRunnable() {
}@Overridepublic void run() {}
}
class Main {
public static void main(String[] args) {
MyRunnable a = new MyRunnable('A');
MyRunnable b = new MyRunnable('B');
Thread demoa = new Thread(a); Thread demob = new Thread(b); demoa.start(); demob.start();}
}
关于选择继承Thread还是实现Runnable接口?
其实Thread也是实现Runnable接口的:
class Thread implements Runnable {
//…
public void run() {
if (target != null) {
target.run();
}
}
}
Thread中的run方法调用的是Runnable接口的run方法。Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式。
Thread和Runnable的区别
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
class MyThread implements Runnable{
private int ticket = 5; //5张票public void run() { for (int i=0; i 0) { System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--); } }}
}
public class lzwCode {
public static void main(String [] args) { MyThread my = new MyThread(); new Thread(my, "1号窗口").start(); new Thread(my, "2号窗口").start(); new Thread(my, "3号窗口").start();}
}
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。
主线程和子线程之间的关系
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM就是在操作系统中启动了一个进程。
主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。
// 休眠两秒Thread.sleep(2000);// 强制加入thread.join();// 后台线程thread.setDaemon(true);/ * @author Rollen-Holt 后台线程 * */class hello implements Runnable { // 虽然有一个死循环,但是程序还是可以执行完的。因为在死循环中的线程操作已经设置为后台运行了。 public void run() { while (true) { System.out.println(Thread.currentThread().getName() + "在运行"); } } public static void main(String[] args) { hello he = new hello(); Thread demo = new Thread(he, "线程"); demo.setDaemon(true); demo.start(); }}// 优先级// 不要误以为优先级越高就先执行。谁先执行还是取决于谁先去的CPU的资源。thread.setPriority(8);// 礼让// 在线程操作中,也可以使用yield()方法,将一个线程的操作暂时交给其他线程执行。Thread.currentThread().yield();
同步和死锁
/
@author Rollen-Holt
*/
class hello implements Runnable {
public void run() {
for(int i=0;i0){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(count--);
}
}
}public static void main(String[] args) {
hello he=new hello();
Thread h1=new Thread(he);
Thread h2=new Thread(he);
Thread h3=new Thread(he);
h1.start();
h2.start();
h3.start();
}
private int count=5;
}
//【运行结果】:
// 5
// 4
// 3
// 2
// 1
// 0
// -1
这里出现了-1,显然这个是错的。应该票数不能为负值。
如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,其他的线程必须等到这个线程结束之后才能继续执行。
使用线程同步解决问题
使用同步代码块和同步方法
同步代码块
synchronized(同步对象){ //需要同步的代码}
/
@author Rollen-Holt
*/
class hello implements Runnable {
public void run() {
for(int i=0;i0){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(count--);
}
}
}
}public static void main(String[] args) {
hello he=new hello();
Thread h1=new Thread(he);
Thread h2=new Thread(he);
Thread h3=new Thread(he);
h1.start();
h2.start();
h3.start();
}
private int count=5;
}同步方法
synchronized 方法返回类型方法名(参数列表){
// 其他代码
}
/
@author Rollen-Holt
*/
class hello implements Runnable {
public void run() {
for (int i = 0; i 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count--);
}
}public static void main(String[] args) {
hello he = new hello();
Thread h1 = new Thread(he);
Thread h2 = new Thread(he);
Thread h3 = new Thread(he);
h1.start();
h2.start();
h3.start();
}private int count = 5;
}死锁
当多个线程共享一个资源的时候需要进行同步,但是过多的同步可能导致死锁。
生产者,消费者问题
/
面包类,用于存放厨师生产的面包
*/
public class Bread {
private String producer;
public Bread(String producer) { super(); this.producer = producer;}@Overridepublic String toString() { return producer;}
}
/*
篮子类,用于存放面包
篮子假定最多放10个面包
*/
public class Basket {
private int index = 0;
private Bread[] arrayBread = new Bread[10];/*
此方法用于往篮子里扔面包 每当厨师生成好一个面包就往篮子里边扔 由于当某一个厨师在往篮子扔面包的过程(还没扔完,但是面包已经在篮子里),
又有一个厨师要往篮子里扔面包。 如果这是篮子里已经有9个面包的话,最后一个厨师就不能在扔了。
所以需要给这个方法加把锁,等一个厨师扔完后,另外一个厨师才能往篮子里扔。
*/
public synchronized void push(int id, Bread bread) {
System.out.println("生成前篮子里有面包:" + index + " 个");
// 当厨师发现篮子满了,就在那里不停的等着
while (index == arrayBread.length) {
System.out.println("篮子满了,我开始等等。。。。。。");
try {
// 厨师(一个生产线程)开始不停等待
// 他需要等待顾客(一个消费线程)把它叫醒
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}// 唤醒一个正在等待的线程,如果唤醒的线程为生产线程,则又会进入等待状态,
// 如果为消费线程,则因生产线程生产了面包的缘故,消费线程可以进行消费
this.notify();
arrayBread[index] = bread;
index++;
System.out.println(bread);
}
/*
此方法用于往篮子里拿面包 加锁原因和上边一样
*/
public synchronized Bread pop(int id) {
System.out.println("消费前篮子里有面包:" + index + " 个");
while (index == 0) {
System.out.println("篮子空了,我开始等等。。。。。。");
try {
// 顾客(一个消费线程)开始不停等待
// 他需要等待厨师(一个生产线程)把它叫醒
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}// 唤醒一个正在等待的线程,如果唤醒的线程为消费线程,则又会进入等待状态,
// 如果为生产线程,则因生产线程消费了面包的缘故,生产线程可以进行生产
this.notify();
index--;
System.out.println("第" + id + "个顾客消费了 -->" + arrayBread[index]);
return arrayBread[index];
}
}
/*
厨师类,用于生产面包
*/
public class Kitchener implements Runnable {
private Basket basket;
private int id;public Kitchener(int id,Basket basket) {
super();
this.id = id;
this.basket = basket;
}@Override
public void run() {
//让厨师生产10个面包
for (int i = 1; i
名字和年龄对应错误了,
http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html
关键字:产品经理
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!