您的位置:首页 > 编程语言 > Java开发

【线程】Java线程(1)-线程基本理解and实现方式

2014-04-22 15:28 337 查看

1、关于进程和线程,在知乎上看到一个很漂亮的解释。

【来源:pansz,自由软件开发者,地址:多线程有什么用?(CSDN禁用了知乎的URL,为什么?)】

1。单进程单线程:一个人在一个桌子上吃菜。

2。单进程多线程:多个人在同一个桌子上一起吃菜。

3。多进程单线程:多个人每个人在自己的桌子上吃菜。

多线程的问题是多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了。。。此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢。

1。对于 Windows 系统来说,【开桌子】的开销很大,因此 Windows 鼓励大家在一个桌子上吃菜。因此 Windows 多线程学习重点是要大量面对资源争抢与同步方面的问题。

2。对于 Linux 系统来说,【开桌子】的开销很小,因此 Linux 鼓励大家尽量每个人都开自己的桌子吃菜。这带来新的问题是:坐在两张不同的桌子上,说话不方便。因此,Linux 下的学习重点大家要学习进程间通讯的方法。

--

补充:有人对这个开桌子的开销很有兴趣。我把这个问题推广说开一下。

开桌子的意思是指创建进程。开销这里主要指的是时间开销。

可以做个实验:创建一个进程,在进程中往内存写若干数据,然后读出该数据,然后退出。此过程重复 1000 次,相当于创建/销毁进程 1000 次。在我机器上的测试结果是:

UbuntuLinux:耗时 0.8 秒

Windows7:耗时 79.8 秒

两者开销大约相差一百倍。

这意味着,在 Windows 中,进程创建的开销不容忽视。换句话说就是,Windows 编程中不建议你创建进程,如果你的程序架构需要大量创建进程,那么最好是切换到 Linux 系统。

大量创建进程的典型例子有两个,一个是 gnu autotools 工具链,用于编译很多开源代码的,他们在 Windows 下编译速度会很慢,因此软件开发人员最好是避免使用 Windows。另一个是服务器,某些服务器框架依靠大量创建进程来干活,甚至是对每个用户请求就创建一个进程,这些服务器在 Windows 下运行的效率就会很差。这"可能"也 是放眼全世界范围,Linux 服务器远远多于 Windows 服务器的原因。

浏览器浏览一个页面,里面有很多图片,多线程,每个线程下载一副图片,他们相当于一个桌子上不同的菜。

浏览器开了多个标签浏览不同网站,多进程,因为他们相当于"不同的桌子"。

2、线程的实现方式

1)、继承Thread。

public class ExtendsThread extends Thread{
	public void run(){
		System.out.println("继承Thread实现线程");
	}
}
2)、实现Runable()接口。

public class ImplRunable implements Runnable{
	public void run() {
		System.out.println("实现Runable实现线程");
	}
}
本质都需要重写run方法。
Test类

public class Test {
	public static void main(String[] args) {
		Thread exThread = new ExtendsThread();
		exThread.start();
		Thread imtThread = new Thread(new ImplRunable());
		imtThread.start();
	}
}
两种实现方式也经常可以这样写:

new Thread(){
	public void run(){
		System.out.println("继承Thread实现线程");
	}
}.start();
new Thread(new Runnable() {
	public void run() {
		System.out.println("实现Runable实现线程");
		}
}).start();

3、两种实现方式的区别

Thread是类,而Runnable是接口;Thread本身是实现了Runnable接口的类。我们知道"一个类只能有一个父类,但是却能实现多个接口",因此Runnable具有更好的扩展性。

此外,Runnable还可以用于"资源的共享"。即,多个线程都是基于某一个Runnable对象建立的,它们会共享Runnable对象上的资源。

通常,建议通过"Runnable"实现多线程!

关于共享资源,举例说明:

1)、impl Runable实现

public class RunThread implements Runnable{
	private int money = 100;
	public void run() {
		for (int i = 1; i <= 5; i++) {
			money--;
			System.out.println(Thread.currentThread().getName()+" "+money);
		}
	}
}


虽然两个线程可能不是依次执行的,但是最后结果是90。因为两个线程处理的是一个变量。

2)、extends Thread实现

public class ExThread extends Thread{
	private int money = 100;
	public void run() {
		for (int i = 1; i <= 5; i++) {
			money--;
			System.out.println(Thread.currentThread().getName()+" "+money);
		}
	}
}


最后的结果是95,两个线程处理的是各自的变量。

Main.Java(测试类)

public class Main {
	public static void main(String[] args) {
		RunThread thread = new RunThread();
		new Thread(thread, "1").start();
		new Thread(thread, "2").start();
		ExThread exThread1 = new ExThread();
		exThread1.start();
		ExThread exThread2 = new ExThread();
		exThread2.start();
	}
}

4、关于Thread

回到Java API,看看关于Thread的说明:

public class Thread
extends Object
implements Runnable
Runable是一个接口,如果针对线程直接调用run,和普通方法无异。

查看Thread.start()方法,

public synchronized void start() {
    if (started)
        throw new IllegalThreadStateException();
	started = true;
    group.add(this);
    start0();
}
private native void start0();
做了同步处理,并且如果线程已经启动,会抛出IllegalThreadStateException异常。

否则的话,在内部调用了start0方法,查看该方法,native,和操作系统做了交互。

【参考】:(URL被csdn禁用了)

1、pansz,自由软件开发者,地址:多线程有什么用?

2、Java多线程系列--"基础篇"02之 常用的实现多线程的两种方式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: