java多线程的讲解(上)
1.什么是进程? 2.什么是线程? 3.java如何实现多线程。 4.Thread类常见的方法。 5.线程安全问题如何解决。
1.什么是进程
进程是计算机中运行中的程序的实例。它是操作系统分配资源(如内存、CPU)并管理程序执行的基本单位。
目前操作系统都是支持多进程的,可以同时发执行多个进程,通过进程ID区分。单核CPU在同一时刻,只能有一个进程;宏观并行,围观串行。
2.什么是线程
线程,又称轻量级进程(Light Weight Process)。线程是进程中的一条执行路径,也是CPU的基本调度单位。若一个程序可同一时间执行多个线程,就是支持多线程的,一个进程优一个或多个线程组成,彼此之间完成不同的工作,同时执行,称为多线程。
3.Java创建多线程的方式
3.1继承Thread来完成多线程
1.创建一个线程类,继承Thread
2, 重写run方法,---写自己线程的任务代码
3,在主函数中创建线程对象,并开启线程,.start()
public class Test01 { public static void main(String[] args) { MyThread myThread = new MyThread();//实例化对象 myThread.start();//调用线程主体 for(int i=0;i<25;i++){ System.out.println("main主体线程~~~~~~~~"+i); } } }
public class MyThread extends Thread{ //Thread 表示线程类 @Override public void run() { //重写run方法: 当线程启动后,会调用run方法体中的代码 for(int i=0;i<25;i++){ System.out.println("线程=========="+i); } } }
3.2实现Runnable接口
public class Test02 { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable();//实例化对象, Thread thread = new Thread(myRunnable);//实例化Thread类对象 thread.start();//启动线程 for(int i=0;i<25;i++){ System.out.println("main主体线程~~~~~~~~"+i); } } }
public class MyRunnable implements Runnable {//实现Runnable接口,作为线程的实现类 @Override public void run() {//重写run方法,作为线程的操作主体 for(int i=1;i<25;i++){ System.out.println("线程B~~~~~~~~~~~~"+i); } } }
是选用Thread类还是Runnable类
java只允许单继承,但是可以实现多接口,选择第一种继承Thread方式,那么就无法继承别的类,不利于扩充。
3.3实现Callable接口
暂无,待补充
4.Thread常见的方法
4.1
static Thread currentThread() 获取当前线程对象 String getName() 获取线程对象名字 void setName(String name) 修改线程对象名字
public class Test01 { public static void main(String[] args) { MyThread myThread = new MyThread();//实例化对象 myThread.start();//调用线程主体 //myThread.setName("A计划"); //修改线程对象名称 //Thread.currentThread.setName("main计划"); for(int i=0;i<25;i++){ //获取当前线程对象名称,通用 System.out.println("2"+Thread.currentThread().getName()+"main主体线程~~~~~~~~"+i); } } }
public class MyThread extends Thread{ //Thread 表示线程类 @Override public void run() { //重写run方法: 当线程启动后,会调用run方法体中的代码 for(int i=0;i<25;i++){ //this.getName获取当前前程的名称, ---该方法只能用于Thread的子类 System.out.println("1"+this.getName()+"线程=========="+i); } } }
4.2
static void sleep(long millis) 让当前线程休眠millis秒 static void yield() 让位方法,当前线程暂停,回到就绪状态,让给其它线程。
void setPriority(int newPriority) 设置线程优先级 1-10
void join() 将一个线程合并到当前线程中,当前线程受阻塞,加入的线程执行直到结束后,当前前程才会执行。
setDaemon(boolean on) on为true表示把线程设置为守护线程
public class Test03 { public static void main(String[] args) { MyThread2 myThread2 = new MyThread2(); myThread2.start(); myThread2.setName("第一"); for(int i=1;i<25;i++){ System.out.println("main~~~~~~~~~"+i); } } }
public class MyThread2 extends Thread{ @Override public void run() { for(int i=1;i<20;i++){ try { //1休眠 this.sleep(1000); //重写的方法,抛出的异常不能超过父类 } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(this.getName()+"---------------"+i); } } }
public class Test04 { public static void main(String[] args) { MyThread2 myThread21 = new MyThread2(); MyThread2 myThread2 = new MyThread2(); myThread2.setPriority(10);//2设置优先级 myThread21.setPriority(1);//2设置优先级 myThread2.start(); myThread21.start(); for(int i=1;i<25;i++){ System.out.println("main~~~~~~~~~"+i); } } }
public class MyThread4 extends Thread{ @Override public void run() { for(int i=1;i<20;i++){ //Thread.yield();//3让位 当前线程暂停,回到就绪状态,让给其它线程。 System.out.println(this.getName()+"---------------"+i); } } }
public class Test05 { public static void main(String[] args) throws InterruptedException { MyThread2 myThread2 = new MyThread2(); //4 myThread2.join();//myThread2线程加入了主线程当中,main线程需要等myThread2线程执行完才会执行 myThread2.setDaemon(true);//5 设置myThread2线程为守护线程--后台线程。---当main线程执行完毕后,守护线程会结束 myThread2.start(); for(int i=1;i<25;i++){ System.out.println("main~~~~~~~~~"+i); } } }
public class MyThread5 extends Thread{ @Override public void run() { for(int i=1;i<50;i++){ System.out.println(this.getName()+"---------------"+i); } } }
5.线程安全问题如何解决
当前卖票系统出现安全问题,解决线程安全问题
当多个线程共享一个资源时,可能会出现线程安全问题
如何解决线程安全问题?----使用锁。----》 凡是用锁 锁定的代码都是原子操作。
第一种自动锁:synchronized
第二种手动锁:Lock
public class Test07 { private static String[] arr= new String[2]; private static int index=0; public static void main(String[] args) throws InterruptedException { // MyThread7 my7 =new MyThread7(); // Thread m1 =new Thread(my7,"商品A"); // Thread m2 =new Thread(my7,"商品B"); // Thread m3 =new Thread(my7,"商品C"); // Thread m4 =new Thread(my7,"商品D"); // m1.start(); // m2.start(); // m3.start(); // m4.start(); Thread t01 = new Thread(new Runnable() { @Override public void run() { synchronized (arr){ if(arr[index]==null){ arr[index]="hello"; index++; }} } }); Thread t02= new Thread(new Runnable() { @Override public void run() { synchronized (arr){ if(arr[index]==null){ arr[index]="world"; index++; }} } }); t01.start(); t02.start(); t01.join(); t02.join(); //arr.toString() System.out.println(Arrays.toString(arr)); } }
public class MyThread7 extends Thread{ private int ticket=100; private Lock lo= new ReentrantLock();//手动上锁 @Override public void run() { while (true){ //synchronized (this){ //自动上锁和释放锁 // if(ticket>0){ // ticket--; // System.out.println(Thread.currentThread().getName()+"卖了一张票,还剩"+ticket); // }else{ // break; // } // } lo.lock();//手动上锁 if(ticket>0){ ticket--; System.out.println(Thread.currentThread().getName()+"卖了一张票,还剩"+ticket); }else{ break; } lo.unlock();//手动解锁 } } }
待续......