java-线程(一)
1.进程与线程的区别
多个进程的内部数据和状态都是完全独立的,而多个线程是共享一块内存空间和一组系统资源,有可能互相影响。多线程程序比多进程程序需要更少的管理费用。进程是重量级的任务,需要分配他们的单独的地址空间。进程间通信是昂贵和受限的,进程间的切换也是很需要花费的。另一方面,线程是轻量级的选手,他们共享相同的地址空间并且共享同一个进程。线程间通信是便宜的,县城建的转化也是低成本的
线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担要小。
比如:搬砖(一个进程),一个人搬,则是一个线程,是顺序执行的。五个人搬,则是五个线程。
2.什么是多线程
多线程是指在单个程序中可以同时运行不同的线程来执行的不同的任务。线程是程序内的顺序控制流,只能使用分配给程序的资源和环境。多线程的目的:最大限度的利用CPU。
例子:当程序启动运行时,就自动产生一个线程,主方法main就在这个主线程上面运行。
3.进程:执行中的程序(程序是静态的,进程是动态的),一个进程可以包含一个或者多个线程(Thread)。
4.线程的实现
在java中通过run方法为线程指明要完成的任务,有两种技术来为线程提供run方法。
1)集成Thread类并重写run方法,然后通过srart方法来启动线程,start方法首先为线程的执行准备好系统资源,然后调用run方法。当一个类集成了Thread类,就变成了一个线程
2)通过定义实现Runnable接口的类进而实现run方法,必须通过start方法来启动线程。
简单例子:
public class ThreadTest { public static void main(String[] args) { Thread1 t1 = new Thread1("first thread"); Thread1 t2 = new Thread1("second thread"); System.out.println(t1.getName()); System.out.println(t2.getName()); t1.start(); t2.start(); } } class Thread1 extends Thread { public Thread1(String name) { super(name); } @Override public void run() { for(int i = 0; i < 100; i++) { System.out.println("hello world: " + i); } } } class Thread2 extends Thread { public Thread2(String name) { super(name); } @Override public void run() { for(int i = 0; i < 100; i++) { System.out.println("welcome: " + i); } } }
public class ThreadTest2 { public static void main(String[] args) { // Thread t1 = new Thread(new Runnable() // { // @Override // public void run() // { // for(int i = 0; i < 100; i++) // { // System.out.println("hello :" + i); // } // } // }); // // t1.start(); Thread t1 = new Thread(new MyThread()); t1.start(); Thread t2 = new Thread(new MyThread2()); t2.start(); } } class MyThread implements Runnable { @Override public void run() { for(int i = 0; i < 100; i++) { System.out.println("hello :" + i); } } } class MyThread2 implements Runnable { @Override public void run() { for(int i = 0; i < 100; i++) { System.out.println("welcome: " + i); } } }
Thread 和 Runnable的区别
1.Thread类也实现了Runnable接口,因此实现了Runnable接口中的run方法。
2.当生成一个线程对象时,如果没有为其设定名字,那么线程对象的名字将使用如下形式:Thread-number
3.当使用Thread生成线程对象时,我们需要重写run方法,因为Thread类的run方法此时什么也不做
4.当使用Runnable实现线程对象时,需要实现Runnable接口中的run方法,然后使用new Thread(new MyThread())来生成线程对象,这时的线程对象的run方法就会调用Muthread类的run发放,这样就使用我们自己编写的run方法了
线程的生命周期
1)创建状态
2)可运行状态
3)不可运行状态:sleep(long millis);线程调用wait方法等待特定条件的满足;线程输入、输出阻塞。
4)消亡状态
返回可运行状态条件:处于睡眠状态的线程在制定的时间过去后;如果线程在等待某一条件,另一个对象必须通过notify()或notifyAll()方法通知等待线程条件的改变;如果线程是因为输入/输出阻塞,等待输入/输出完成。
为什么要引入同步机制
在多线程环境中,可能会有两个甚至更多的线程试图访问一个有限的资源,必须对这种潜在资源冲突进行预防。
解决方法:在线程使用一个资源时为其加锁即可。访问资源的第一个线程为其加上锁后,其他线程便不能再使用那个资源,除非被解锁。
synchronized关键字:当synchronized关键字修改一个方法的时候,该方法叫做同步方法。
java中的每一个对象都有一个锁(lock)或者叫做监视器(monitor),当访问某个对象的synchronized方法时,表示将该对象上锁,此时其他任何线程都无法再次访问该synchronized方法了,直到之前的那个线程执行方法完毕后(或者抛出异常),那么将该对象的锁释放掉,其他线程才能有可能再去访问该synchronized方法。
1 public class ThreadTest4 2 { 3 public static void main(String[] args) 4 { 5 Example example = new Example(); 6 7 Thread t1 = new TheThread(example); 8 9 example = new Example(); 10 11 Thread t2 = new TheThread2(example); 12 13 t1.start(); 14 t2.start(); 15 } 16 } 17 18 class Example 19 { 20 public synchronized static void execute() 21 { 22 for(int i = 0; i < 20; i++) 23 { 24 try 25 { 26 Thread.sleep((long)(Math.random() * 1000)); 27 } 28 catch (InterruptedException e) 29 { 30 e.printStackTrace(); 31 } 32 33 System.out.println("hello: " + i); 34 } 35 } 36 37 public synchronized static void execute2() 38 { 39 for(int i = 0; i < 20; i++) 40 { 41 try 42 { 43 Thread.sleep((long)(Math.random() * 1000)); 44 } 45 catch (InterruptedException e) 46 { 47 e.printStackTrace(); 48 } 49 50 System.out.println("world: " + i); 51 } 52 } 53 } 54 55 56 class TheThread extends Thread 57 { 58 private Example example; 59 60 public TheThread(Example example) 61 { 62 this.example = example; 63 } 64 65 @Override 66 public void run() 67 { 68 this.example.execute(); 69 } 70 } 71 72 class TheThread2 extends Thread 73 { 74 private Example example; 75 76 public TheThread2(Example example) 77 { 78 this.example = example; 79 } 80 81 @Override 82 public void run() 83 { 84 this.example.execute2(); 85 } 86 }