Java的进程和线程
进程是指一个内存中运行的程序,每个进程都有自己的一块独立内存空间,一个进程可以有多个线程。比如在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之后就不能继承其它类
从代码的简单性来说,继承方式简单些。
推荐使用接口方法,方便以后拓展,而且资源共享。