------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
进程是指一个内存中运行的程序,每个进程都有自己的一块独立内存空间,一个进程可以有多个线程。比如在Window中运行一个xx.exe就是一个进程。
Java程序的进程里有几个线程:主线程、垃圾回收线程(后台线程)。
线程指的是进程中的一个执行任务,一个进程可以执行多个线程,多个线程可以共享数据。
多进程:就是在操作系统中同时运行多个程序.......
多线程:在同一个进程中同时运行多个任务.......
一个进程至少有一个线程,为了提高效率,可以在一个进程中开启多个任务。
线程可以同时运行,但是通过程序运行的结果发现,虽然同时运行,但是每次结果都不一样。
因为多线程存在一个特性:随机性。
造成原因:CPU在瞬间不断切换去处理各个线程而导致的。
可以理解为多个线程在抢CPU资源。
线程具有许多传统进程所具有的特征,可以成为轻型进程。
而把传统的进程成为重型进程,它相当于只有一个线程在执行任务。在引入了线程的操作系统中,通常一个进程有若干个线程,至少有一个线程。
进程与线程的区别:
1、进程有独立的进程空间,进程中的数据存放空间,也就是堆空间与栈空间,它们是独立的。
2、线程的堆空间是共享的,栈空间是独立的,线程消耗的资源比进程小,相互之间可以影响的。
创建线程的方法:
1、继承Thread类
1 package xiao.li;
2
3 public class 继承Thread类方式创建线程 {
4
5 /**
6 * @param args
7 */
8 public static void main(String[] args) {
9 //Thread.currentThread()返回当前线程的对象
10 String name=Thread.currentThread().getName();//返回主线程名
11 //主线程与子线程是同时运行的。
12 for (int i = 1; i <=50; i++) {
13 System.out.println(name+"--->"+i);
14 if(i==20)
15 {
16 //创建线程并启动线程
17 new MyThread().start();//启动线程,其实就是调用run方法。
18 //new MyThread().run();//如果这样写的话不是启动线程,而是在调用普通方法而已。
19 }
20 }
21
22 }
23 }
24 /*
25 * 继承方式创建线程
26 */
27 class MyThread extends Thread
28 {
29 /*
30 * 覆写Thread类的run方法
31 */
32 public void run() {
33 for (int i = 1; i <=50; i++) {
34 /*
35 * this.getName()这个方法返回的是线程名:Thread-0。
36 * this.setName(String name)这个方法是设置线程名。
37 */
38 System.out.println(this.getName()+i);
39 }
40 }
41 }
2、实现Runnable接口
1 package xiao.li;
2
3 public class 实现Runnable接口方式创建线程 {
4
5 /**
6 * @param args
7 */
8 public static void main(String[] args) {
9 //创建子线程对象
10 MyThread1 my = new MyThread1();
11 for (int i = 0; i < 50; i++) {
12 System.out.println(Thread.currentThread().getName()+"---->"+i);
13 if(i==25)
14 {
15 //创建线程,设置子线程名并启动线程
16 new Thread(my,"leo").start();
17 }
18 }
19
20 }
21
22 }
23 /*
24 * 实现Runnable接口方式创建线程
25 */
26 class MyThread1 implements Runnable
27 {
28
29 /*
30 * 实现run方法
31 */
32 public void run() {
33 //通过Thread.currentThread().getName()获取当前线程的名字,不能像继承Thread类那样直接调用getName()方法
34 for (int i = 0; i < 50; i++) {
35 System.out.println(Thread.currentThread().getName()+"--->"+i);
36 }
37 }
38 }
这两种方法的运行结果:每运行一次结果都会不一样!
Thread卖票实例:
1 package xiao.li;
2
3 public class 继承方式多线程卖票的例子 {
4
5 /**
6 * @param args
7 */
8 public static void main(String[] args) {
9 // TODO Auto-generated method stub
10 new TicketThread("1号窗口").start();
11 new TicketThread("2号窗口").start();
12 new TicketThread("3号窗口").start();
13 /*
14 * 上面这种方法会重复卖票...
15 */
16 }
17 }
18 class TicketThread extends Thread
19 {
20 TicketThread(String name)
21 {
22 super(name);
23 }
24 int ticketNumber=10;
25 public void run() {
26 for (int i = 0; i < ticketNumber; i++) {
27 System.out.println(this.getName()+"卖出"+ticketNumber--+"号票");
28 }
29 }
30 }
结果:
1号窗口卖出10号票
1号窗口卖出9号票
1号窗口卖出8号票
1号窗口卖出7号票
1号窗口卖出6号票
2号窗口卖出10号票
2号窗口卖出9号票
2号窗口卖出8号票
2号窗口卖出7号票
2号窗口卖出6号票
3号窗口卖出10号票
3号窗口卖出9号票
3号窗口卖出8号票
3号窗口卖出7号票
3号窗口卖出6号票
大家看,如果到火车站去买票,那么售票员就是这样买票的.....会引起冲突!既然1号窗口已经把10号座位卖出去了,为什么2号窗口还要继续卖呢?所以这样很不好......
Runnable:
1 package xiao.li;
2
3 public class 实现接口方式多线程卖票例子 {
4
5 /**
6 * @param args
7 */
8 public static void main(String[] args) {
9 // TODO Auto-generated method stub
10 MyTicket target = new MyTicket();
11 new Thread(target,"1号窗口").start();
12 new Thread(target,"2号窗口").start();
13 new Thread(target,"3号窗口").start();
14 }
15 }
16 class MyTicket implements Runnable
17 {
18 private int ticketNumber=10;
19 //实现run方法
20 public void run() {
21 for (int i = 0; i <= 200; i++) {
22 if(this.ticketNumber>0)
23 {
24 System.out.println(Thread.currentThread().getName()+"卖出"+ticketNumber--+"号票");
25 }
26 }
27 }
28 }
结果:
1号窗口卖出10号票
3号窗口卖出8号票
2号窗口卖出9号票
3号窗口卖出6号票
1号窗口卖出7号票
3号窗口卖出4号票
2号窗口卖出5号票
3号窗口卖出2号票
1号窗口卖出3号票
2号窗口卖出1号票
这两种方法的结果很明显易见......................
比较两种方式的区别:
使用继承的话,资源不能共享。
继承方式,继承了Thread之后就不能继承其它类
从代码的简单性来说,继承方式简单些。
推荐使用接口方法,方便以后拓展,而且资源共享。