一、进程与线程
进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立的控制单元,线程在控制着进程的执行,一个进程中至少有一个线程。
JVM启动时会有java.exe进程,该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中,即为主线程;更确切的说,java虚拟机启动时,不止一个线程,还有负责垃圾回收机制的线程也会启动。
二、创建线程
两种传统方式:
1、在Thread子类中覆盖run()方法,并编写运行代码;
Thread thread = new Thread(){
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1:"+Thread.currentThread().getName());
//System.out.println("2:"+this.getName());//当前线程可以用this表示
}
}
};
thread.start();
2、在传递给Thread对象的Runnable对象的run()方法中编写运行代码。
Thread thread2 = new Thread(new Runnable() {
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("1:"+Thread.currentThread().getName());
}
}
});
thread2.start();
这二种方法的区别:
1、实现Runnable接口创建线程更加体现了面向对象的思维,而且避免了单继承的局限性;
2、继承Thread:线程代码放在子类Thread的run方法中;实现Runnable:线程代码放在接口子类的run方法中。
注意:
1、如果多线程中用到异常语句,只能try,不能在run()方法抛出异常;
2、多线程并不会提高程序的运行效率,CPU来回切换,反而会降低效率;而多线程下载是因为要去抢占服务器端的资源,每个线程的速率其实没有变化;
3、如果在Thread子类覆盖的run方法中编写了运行代码,也为Thread子类对象传递了一个Runnable对象,那么线程运行时会执行子类的run方法;
//Thread子类覆盖了run方法,也传递了Runnable对象,运行结果为:Thread:Thread-0,即运行的是子类的run方法。
Thread thread3 = new Thread(new Runnable(){
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Runnable:"+Thread.currentThread().getName());
}
}
}){
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread:"+Thread.currentThread().getName());
}
}
};
thread3.start();
三、多线程的安全问题
多线程的安全问题:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,CPU进行切换,另一个线程参与进来执行,就会导致共享数据的错误。
安全问题出现的原因:多个线程访问出现延迟,线程的随机性 。
解决办法:
1、同步代码块:对多条线程操作共享数据的语句,只能让一个线程执行完,再让其它线程继续执行,代码格式:
synchronized(对象){
需要同步的代码;
}
2、同步函数:在函数上加上synchronized修饰符即可。例:publicsynchronized void test(){}
同步的前提:
1、必须要有两个或者两个以上的线程;
2、必须是多个线程使用同一个锁;
3、必须保证同步中只能有一个线程在运行。
同步的好处:解决了多线程的安全问题。
同步的弊端:多个线程都会去判断同步锁,较为消耗资源。
同步函数的锁:
1、同步函数需要被对象调用,那么函数都有一个所属对象引用:就是this,所以同步函数使用的锁是this。
2、当同步函数被静态修饰后,静态成员初始化时,内存中还没有本类对象,但是一定有该类对应的字节码文件对象,类名.class,该对象的类型是Class类。所以,静态的同步函数,使用的锁是该函数所在类的字节码文件对象。
四、线程间通信
线程间的通信:其实就是多个线程在操作同一个资源,但是操作的动作不同。
等待唤醒机制:
在操作同步中的线程时,必须标识所操作线程持有的锁;只有同一个锁上的被等待线程才可以被同一个锁上的notify()方法唤醒,不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。
停止线程:
1、让run()方法结束运行:开启多线程运行,通常是循环结构,只要控制了循环,就可以让run方法结束;
2、定义循环结束标记:使用Thread类的interrupt(中断)方法,该方法是结束线程的冻结状态,使线程回到运行状态中来。
package blog.itheima;
/*线程程间通信,同步示例代码:
需求:
有二个线程,子线程先执行10次,然后主线程执行100次,如此交替运行,一共执行50次为止。*/
public class TraditionalThreadCommunication {
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {
//子线程总共执行50次
public void run() {
for(int i=1; i<=50; i++){
/*创建一个对象,把这一段代码当作方法放在对象之中
synchronized (TraditionalThreadCommunication.class) {
for(int j=1; j<=10; j++){
System.out.println(Thread.currentThread().getName()+"...执行次数:"+j+"...第"+i+"次循环");
}
}*/
business.sub(i);
}
}
}).start();
//主线程总共执行50次
for(int i=1; i<=50; i++){
/*synchronized (TraditionalThreadCommunication.class) {
for(int j=1; j<=10; j++){
System.out.println(Thread.currentThread().getName()+"...执行次数:"+j+"...第"+i+"次循环");
}
}*/
business.main(i);
}
}
}
class Business{
private boolean flag = false;
public synchronized void sub(int i){
while(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//初始为false,子线程先执行10次
for(int j=1; j<=10; j++){
System.out.println(Thread.currentThread().getName()+"...执行次数:"+j+"...第"+i+"次循环");
}
//子线程执行10次之后,更改标记进入等待,唤醒主线程
flag = true;
this.notify();
}
public synchronized void main(int i){
//if(!flag){
//初始为false,子线程先执行,主线程等待
while(!flag){//用while会二次判断条件,比if判断一次更健壮
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//子线程执行10次之后,更改标记为true,主线程执行100次
for(int j=1; j<=100; j++){
System.out.println(Thread.currentThread().getName()+"...执行次数:"+j+"...第"+i+"次循环");
}
//主线程执行100次之后,更改标记进入等待状态,唤醒子线程
flag = false;
this.notify();
}
}
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------