多线程初谈——线程的创建与互斥问题

[b][size=large]多线程初谈——线程的创建与互斥[/size][/b]
[size=small]对于线程起初也很是不解,觉得很乱,线程的互斥就跟别提了。创建线程也一直只能通过创建Thread子类的方法,像那个实例化Runnable对象一直不是很理解,也没敢用,二者的线程创建区别在哪也不清楚。带着这些困惑一直到了现在。随着对Android语言的深入学习,发现线程真的很重要,不弄清楚就难以做出一个好的产品,不解决线程的互斥,同步通信,死锁问题,就无法得到一个高质量,高安全的东西。所以趁着国庆期间把线程同步这一块重新学习了一遍。以下是我在学习过程中做出的一些总结,希望对还在苦恼的你有些许帮助。[/size]一、创建线程的两种方法:
[size=small][color=red]1、通过创建Thread子类来实现线程:创建Thread子类,子类中重写run方法覆盖掉父类的run方法。
2、实例化Runnable对象来实现线程:给Thread类的构造函数传一个Runnable对象,再调用Runnable对象中的run方法。(Runnable对象不是线程,是线程要运行的代码的宿主)[/color]
如果对于第二种方法不是很理解,对于为什么要实例化Thread类,再加入对象Runnable有疑问.像代码:[/size]
Thread thread=new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
}
});

[size=small]下面给出一段源代码,我想你这时就知道为什么是这样了。[/size]
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
public void run() {
if (target != null) {
target.run();
}
}

[size=small]由此可见,实例化Runnable接口来创建线程的实质就是,把run方法封装入Runnable对象,再通过Thread的构造方法将Runnable对象传入[/size]。
[size=small]
二、两种方法的些许不同:
[color=red]第二种方法更趋向于面向对象。我们在编码的过程中是面向对象的,第二种方法,是把run方法封装到一个独立对象Runnable中去,然后放入线程对象Thread中.当然在创建线程时,两种方法都是可以的。[/color]
下面给出一段线程创建代码,以供参考[/size]。
public static void main(String args[]){
/*
* 通过创建Thread子类的的构造线程的方法
*/
Thread thread=new Thread(){
//重写父类的run方法
public void run(){
while(true){
try {
//线程休眠0.5秒
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
//打印当前线程名
System.out.println(Thread.currentThread().getName());
}
}
};
thread.start();//线程启动

/*
* 实例化Runnable对象,传入Thread类中来创建线程
*/
Thread thread2=new Thread(new Runnable(){


public void run() {
while(true){
try {
//线程休眠0.5秒
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
//打印当前线程名
System.out.println(Thread.currentThread().getName());
}
}
});
thread2.start();//线程启动



}

[size=small]其运行结果[/size]:

[img]http://dl2.iteye.com/upload/attachment/0089/8376/e5844a69-dcd7-3a84-9047-2d8f76af5ee3.bmp[/img]
[size=small]如果你觉得对两者的创建及些许的区别有很好的了解,那就思考下,下面的代码会输出什么样的结果:[/size]
//创建Thrad子类
new Thread(new Runnable(){//创建Runnable对象,传入Thread中
public void run() {
while(true){
try {
//线程休眠0.5秒
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
//打印当前线程名
System.out.println("runnable:"+Thread.currentThread().getName());
}
}

}){
public void run() {
while(true){
try {
//线程休眠0.5秒
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
//打印当前线程名
System.out.println("thread:"+Thread.currentThread().getName());
}
}
}.start();//开启线程
[size=x-small]运行结果:[/size]
[img]http://dl2.iteye.com/upload/attachment/0089/8388/a1548525-f4e7-322b-9a8c-4dbcd5c06eb0.bmp[/img]

--------------------------------分割线-------------------------------
[size=small]三、线程的互斥问题。
[color=red]线程的互斥就是一个关键字:synchornized.互斥锁定的必须是同一个对象,必须是同一个锁。[/color]
我们在用到多线程操作同一份数据时,就会用上线程的互斥,如果这块不懂的话,代码会出现很严重的逻辑问题和产品安全性问题。就如银行的存取款,如果我原有1000元存款,现在父母往里面又存了500元,同时我在取钱200,如果银行系统线程同步没处理好,那么就很可能出现自己的存款总后只有800元,而不是1300.
下面给出没有加线程互斥的代码:[/size]
public class SteupThread {

public static void main(String args[]){
new SteupThread().init();
}
public void init(){
//内部类不能访问局部变量,为了访问局部变量,需加final
final Output output=new Output();
//线程1
new Thread(new Runnable(){
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.print1("wobeidayinle");
}
}

} ).start();

//线程2
new Thread(new Runnable(){
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.print2("howareyou");
}
}

} ).start();
}
//内部类
class Output{
public void print1(String st){
int len=st.length();
for(int i=0;i<len;i++){
System.out.print(st.charAt(i));
}
System.out.println();
}
public void print2(String st){
int len=st.length();
for(int i=0;i<len;i++){
System.out.print(st.charAt(i));
}
System.out.println();
}
}
}

[size=small]运行结果[/size]:

[img]http://dl2.iteye.com/upload/attachment/0089/8396/34809ca8-e8f9-33c8-8b62-01a08cbbf208.bmp[/img]
[size=small]通过上面的代码可以知道:在打印语句:howareyou时被打断了,为了避免此类事情发生,就必须用到线程的互斥了。
代码改进如下:
[color=red]将内部类Output中的同步方法用synchornized锁定[/size]。[/color]
//内部类
class Output{
public synchronized void print1(String st){
int len=st.length();
for(int i=0;i<len;i++){
System.out.print(st.charAt(i));
}
System.out.println();
}
public synchronized void print2(String st){
int len=st.length();
for(int i=0;i<len;i++){
System.out.print(st.charAt(i));
}
System.out.println();
}
}


[size=small][color=darkred]线程的创建与互斥就总结到此,如果觉得这些简单,认为学懂了线程的互斥,就思考一下这个问题怎么解决吧:[/color]
问:子线程循环10次,接着主线程循环100次,接着又子线程循环10次,然后又主线程循环100次,如此循环50次,请写出相应程序。(此为一次公司招聘面试题!如果没有解决,后面会给出代码,此类为线程同步通信问题。)[/size]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值