Java之多线程(一)

1.多线程的引入

整个程序的执行路径只有一条,叫单线程程序;

如果一个程序的执行路径有多条,叫多线程程序.

2.进程和线程的概念

我们学习多线程,首先先学习什么是进程,线程依赖于进程存在

(1)进程:系统可以进行独立调配并且是一个不可分割的独立单元
            开启一个任务管理器,很多进程(应用软件/某些客户端)

(2)什么是多进程?
    多进程的意义:是为了提高CPU的使用率
    现在计算机都是多进程,假设:在听音乐的同时,也在打游戏..,他们是同时进行的吗?
           他们不是同时进行的,感觉同时,一点点CPU的时间片在同一个时刻在两个进程之间进行高效的切换!
        
(3)什么线程?
    线程:进程的一个独立的单元

    一个进程里面有多个任务,把每一个任务看成一个线程

(4)多线程:
    线程之间在抢占CPU的执行权(抢占资源)
    多线程的执行具有随机性
        
        举例:
        打篮球:1v1    两个人抢占篮球的几率同样大        

                   1v5   5个人抢占篮球的几率大,并不能说一定抢到 (随机性的)

 [面试题] JVM是多线程程序吗?至少有几条线程?
      jvm是多线程的
      至少有2条线程...
             有主线程,main..执行这些代码,能够被Jvm识别

             在执行一些程序的时候,一些对象Jvm释放掉,原因,它开启了垃圾回收线程,里面GC:垃圾回收器(回收一些没有更多引用的对象或者变量...)

3.多线程的实现

 (1)如何实现多线程程序呢?
 要实现多线程程序,需要开启进程;
 开启进程,是需要创建系统资源,但是Java语言不能创建系统资源;
 只有C/C++可以创建系统资源, 利用c语言创建好的系统资源实现;

 Java提供了一个类:Thread类:Java虚拟机允许应用程序并发的运行多个执行线程

[注意]

并行和并发(高并发:MyBatis --->IBatis:半自动化)

*前者逻辑上的同时,指的是同一个时间段内

*后者物理上的同时,指的是同一个时间点

(2) 实现多线程程序的步骤:
         1)将类声明为 Thread 的子类

         2)该子类应重写 Thread 类的 run 方法

         3)在主线程进行该自定义的线程类的对象的创建

public class MyThread extends Thread {

	@Override
	public void run() {
//		System.out.println("helloworld");
		for(int x = 0 ;x <200; x ++) { //两个线程都需要执行这个代码
			System.out.println(x);
		}
	}
}

[注释]MyThread类就是一个执行线程类并且重写Thread类中的run 方法

 

         run()方法里面应该是一些耗时的操作,IO操作/循环语句...

 

public static void main(String[] args) {
		
		//创建MyThread类对象
		/*public void start()使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 
		结果是两个线程并发地运行*/
		
		MyThread t1 = new MyThread() ;
		t1.start();
		//IllegalThreadStateException:非法状态异常,同一个线程只能被执行一次
		//t1.start();
		MyThread t2 = new MyThread() ;
		t2.start();
		
		
	}

[注释]1.执行线程不是run方法 ,run方法的调用相当于一个普通方法的调用

         2.同一个线程只能被执行一次,否则会出现IllegalThreadStateException:非法状态异常

(3)Thread 类提供了一些方法

         public final String getName() :获取线程名称

public class MyThread extends Thread {

	@Override
	public void run() {
		for(int x = 0 ;x < 100 ; x++) {//t1,t2
			System.out.println(getName()+":"+x); //thread-线程编号(从0开始)
		}
	}
}

[注释]在获取线程名称的时候:Thread-0/1/2.....

   public final void setName(String name):给线程起名称

//给线程起名字1)无参构造的形式+setName()

public static void main(String[] args) {
		
		//给线程起名字:无参构造的形式+setName()
		MyThread my1 = new MyThread() ;
		MyThread my2 = new MyThread() ;
		
		
		//给线程起名字
		my1.setName("高圆圆");
		my2.setName("张杨");
		
		//分别启动
		my1.start();
		my2.start();
	}

 

//2)有参构造的形式:有参构造的形式

 

public class MyThread extends Thread {
	public MyThread() {
		
	}
	
	public MyThread(String name) {
		super(name) ;
	}

	@Override
	public void run() {
		for(int x = 0 ;x < 100 ; x++) {//t1,t2
			System.out.println(getName()+":"+x); //thread-线程编号(从0开始)
		}
	}
}
public static void main(String[] args) {

		//public Thread(String name):有参构造的形式
		MyThread t1 = new MyThread("张三") ;
		MyThread t2 = new MyThread("李四") ;
		
		t1.start();
		t2.start();
		
	}

 

public static Thread currentThread():返回当前正在执行的线程对象的引用

 

System.out.println(Thread.currentThread().getName());//main

4.Thread类的一些方法

(1)public final void join():等待该线程终止 ,本身有一个异常:interruputedException 中断异常

//分别创建三个子线程,让第一个子线程执行之后,调用join()等待该线程中,在执行t2,t3线程

public class ThreadJoin extends Thread {
	
	@Override
	public void run() {
		for(int x = 0  ; x < 100 ; x ++) {
			System.out.println(getName()+":"+x);
		}
	}
}

public static void main(String[] args) {
		
		//创建三个子线程
		ThreadJoin t1 = new ThreadJoin() ;
		ThreadJoin t2 = new ThreadJoin() ;
		ThreadJoin t3 = new ThreadJoin() ;
		
		//分别给线程设置名称
		t1.setName("李渊");
		t2.setName("李世明");
		t3.setName("李元霸");
		
		t1.start();
		
		try {
			t1.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		t2.start();
		t3.start();
		
		
	}

规律: 谁设置join()方法,就让这个线程执行完毕,再去执行别的线程!

(2)public static void yield()暂停当前正在执行的线程对象,并执行其他线程

public class ThreadYield extends Thread {

	@Override
	public void run() {//t1,t2子线程都要执行这个run()方法
		for(int x = 0 ;x <100 ; x ++) {
			System.out.println(getName()+":"+x);//
			
		}
		Thread.yield();		 
	}
}

public static void main(String[] args) {
		
		//创建两个子线程对象
		ThreadYield ty1 = new ThreadYield() ;
		ThreadYield ty2 = new ThreadYield() ;
		
		ty1.setName("张三");
		ty2.setName("李四");
		
		//分别启动线程
		ty1.start();
		ty2.start();
	}

(3)public final void setDaemon(boolean on) :true时,表示为守护线程
     将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。(守护线程不会立即结束掉,它会执行一段时间在结束掉)

     该方法必须在启动线程前调用。

public class ThreadDaemon extends Thread {
	
	@Override
	public void run() {
		for(int x = 0 ; x<100; x ++) {
			System.out.println(getName()+":"+x);
		}
	}
}

public static void main(String[] args) {
		
		//创建两个子线程
		ThreadDaemon td1 = new ThreadDaemon() ;
		ThreadDaemon td2 = new ThreadDaemon() ;
		
		td1.setName("张飞");
		td2.setName("关羽");
		
		//在启动之前,设置为守护线程
		td1.setDaemon(true); 
		td2.setDaemon(true);
		
		td1.start();
		td2.start(); 
		
		Thread.currentThread().setName("刘备");
		for(int x =0 ; x < 5 ; x ++) {
			System.out.println(Thread.currentThread().getName()+":"+x);
		}
	}

注意: 当主线程结束后,守护线程不会立即结束掉,它会执行一段时间在结束掉!

(4)跟线程优先级相关的方法:
    public final int getPriority()返回线程的优先级
    public final void setPriority(int newPriority)更改线程的优先级
        线程存在一个默认优先级
         public static final int MAX_PRIORITY 10         最大优先级
         public static final int MIN_PRIORITY 1            最小优先级
         public static final int NORM_PRIORITY 5         默认优先级

public class MyThread extends Thread {
	
	@Override
	public void run() {
		for(int x = 0 ; x <100 ; x ++) {
			System.out.println(getName()+":"+x);
		}
		
	}
	
}

public static void main(String[] args) {
		
		//创建三个子线程
		MyThread t1 = new MyThread() ;
		MyThread t2 = new MyThread() ;
		MyThread t3 = new MyThread() ;
		
//		System.out.println(t1.getPriority()); //5 默认优先级
//		System.out.println(t2.getPriority());
//		System.out.println(t3.getPriority());
		
		t1.setName("林青霞");
		t2.setName("林志颖");
		t3.setName("林彪");
		
		//设置线程优先级
		t1.setPriority(10); 
		t2.setPriority(1);
		t3.setPriority(5);
		
		t1.start();
		t2.start(); 
		t3.start();
	}

(5)public static void sleep(long millis):线程睡眠 指定是时间毫秒值

             throws InterruptedException

public class ThreadSleep extends Thread {

	
	@Override
	public void run() {
		for(int x = 0 ; x <100 ; x ++) {
			//t1,t2
			//t1, 0,1    //t2来了 ,3,4,5,6,7,8	//t1 2 ,,,
			System.out.println(getName()+":"+x+",日期是:"+new Date());
			
			//困了,想睡一秒钟
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		
	}
}	

public static void main(String[] args) {
		
		//创建两个子线程
		ThreadSleep ts1 = new ThreadSleep() ;
		ThreadSleep ts2 = new ThreadSleep() ;
		
		ts1.setName("张三");
		ts2.setName("李四");
		
		ts1.start();
		ts2.start();
	}

注意:sleep()一定要写在for循环里面!

(6)public final void stop() ;强迫线程停止执行。    不会执行了 (过时了),方法能使用的

     public void interrupt()中断线程。 表示中断线程的一种状态   程序还会执行

public class ThreadStop extends Thread {
	
	@Override
	public void run() {
		System.out.println("程序开始了....");
		
		//睡秒10秒钟
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
//			e.printStackTrace();
			System.out.println("程序出现异常了...");
		}
		
		System.out.println("程序结束了....");
	}
}

public static void main(String[] args) {
		
		//创建ThreadStop类对象
		ThreadStop st = new ThreadStop() ;
		
		st.start() ;
		
		//如果3秒不醒来,我就干掉你
		try {
			st.sleep(3000);
//			st.stop();
			st.interrupt();// 中断
		} catch (InterruptedException e) {
//			e.printStackTrace();
			System.out.println("程序出现了中断异常");
		}
		
	}

 

[面试题1]stop()和interrupt()的区别?

 

public final void stop() ;强迫线程停止执行。    不会执行了 (过时了),方法能使用的

public void interrupt()中断线程。 表示中断线程的一种状态   程序还会执行

[面试题2]wait()和sleep()的区别?

wait(): wait()调用的时候,立即释放锁  (同步锁/Lock锁)

sleep():    线程睡眠,调用不会释放锁

 

 

5.实现多线程程序的第二种方式

1)自定义一个类,实现Runnable接口
2)实现接口中的run方法,对耗时的代码进行操作
3)然后在主线程中创建该对象,将该类对象做为一个资源类,创建Thread类的对象,将刚才的资源类作为参数进行传递

//自定义类实现接口,实现run方法
public class MyThread implements Runnable {

	@Override
	public void run() {
		
		for(int x= 0; x <100 ; x ++) {
//			System.out.println(getName()+":"+x);
			System.out.println(Thread.currentThread().getName()+":"+x);
		}
	}

}

public static void main(String[] args) {
		
		//创建当前类对象
		MyThread my =new MyThread() ;
		
		//实现多线程
		//public Thread(Runnable target,String name)
		Thread t1 = new Thread(my, "高圆圆") ;
		Thread t2 = new Thread(my, "赵又廷") ;
		
		//启动线程
		t1.start();
		t2.start();
	}

 

 

 
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值