Java初学—多线程
一、进程和线程的区别
进程是指程序的应用实例,会占用独立的内存空间和系统资源
线程是指CPU的调度和分派的基本单位,统一程序 执行多个操作叫做线程
1.什么是多线程
如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程” 多个线程交替占用CPU资源,而非真正的并行执行
2.多线程好处
充分利用CPU的资源 简化编程模型 带来良好的用户体验
3.主线程
main()方法即为主线程入口 产生其他子线程的线程 必须最后完成执行,因为它执行各种关闭动作
二、多线程的创建方式
方法一:继承Thread类 编写简单,可直接操作线程 适用于单继承
package dome2; public class MyThread extends Thread { //创建自定义线程 重写run方法 public void run() { for (int i = 0; i < 10; i++) { //Thread.currentThread()方法获取当前线程 System.out.println(Thread.currentThread().getName()+i); } } public static void main(String[] args) { //创建线程对象 MyThread t1=new MyThread(); //启动线程 t1.start(); } }
方法二:实现Runnable接口 避免单继承局限性 便于共享资源
package dome3; public class MyRunble implements Runnable { public void run() { for (int i = 0; i < 10; i++) { System.out.println(i); } } public static void main(String[] args) { //创建自定义线程实现runnable接口 从写方法 MyRunble my=new MyRunble(); //实例化线程 Thread t1=new Thread(my); //启动线程 t1.start(); } }
三、线程的状态
package dome4; public class Threadzhuangtai implements Runnable{ public void run() { System.out.println("线程正在运行"); try { Thread.sleep(500); System.out.println("线程处于阻塞状态"); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("线程被中断"); } } public static void main(String[] args) { Threadzhuangtai threadzhuangtai=new Threadzhuangtai(); System.out.println("线程处于新建状态"); Thread t1=new Thread(threadzhuangtai); t1.start(); System.out.println("线程处于就绪状态"); } }
四、线程的优先级和休眠
线程调度指按照特定机制为多个线程分配CPU的使用权
1.线程的优先级休眠 线程终止
package dome5; public class youixanji implements Runnable { public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } public static void main(String[] args) { //创建自定义线程实现runnable接口 从写方法 //实例化实现的接口类 youixanji my=new youixanji(); youixanji my2=new youixanji(); youixanji my3=new youixanji(); youixanji my4=new youixanji(); //实例化线程 将实例化的接口类对象放在线程的构造函数内 Thread t1=new Thread(my,"1"); Thread t2=new Thread(my2,"2"); Thread t3=new Thread(my3,"3"); Thread t4=new Thread(my4,"4"); //设置优先级 t1.setPriority(Thread.MAX_PRIORITY); t2.setPriority(Thread.MIN_PRIORITY); //启动线程 t1.start(); t2.start(); //让线程4暂停 其他线程运行 try { t4.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t4.start(); //让线程三休眠5秒 try { t3.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } t3.start(); } }
2.线程的礼让
线程的礼让只提供一种可能 但是并不能一定会实现礼让
package dome6; /* * 线程礼让的实现 */ public class Myrunnable implements Runnable{ //当i==3是线程礼让 当前CPU资源让出 public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+"运行"+i); if (i==3) { Thread.yield(); System.out.println("线程礼让"); } try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { Thread t1=new Thread(new Myrunnable(),"线程一"); Thread t2=new Thread(new Myrunnable(),"线程二"); t1.start(); t2.start(); } }
五、线程不安全的问题
1.当多个线程共享一个资源时,一个线程未完成全部操作时,让其他线程修改数据会造成数据不安全的问题为此为了解决该问题要应用 synchronized关键字来实现线程的同步操作
2.同步方法解决问题:
package dome7; public class Site implements Runnable { private int count = 10;// 剩余票数 private int num = 0;// 第几张票 boolean flag = true; public void run() { while (flag) { stie(); } } public synchronized void stie() { if (count > 0) { count--; num++; System.out.println(Thread.currentThread().getName() + "抢到了第" + num + "张票剩余:" + count); flag = true; } else { flag = false; } } }
创建测试类
package dome7; public class Test { public static void main(String[] args) { Site s=new Site(); Thread t1=new Thread(s,"黄牛党"); Thread t2=new Thread(s,"抢票代理"); Thread t3=new Thread(s,"12306"); t1.start(); t2.start(); t3.start(); } }
3.同步代码块解决问题
public class Site implements Runnable { private int count = 10;// 剩余票数 private int num = 0;// 第几张票 boolean flag = true; public void run() { synchronized (this) { while (flag) { if (count > 0) { count--; num++; System.out.println(Thread.currentThread().getName() + "抢到了第" + num + "张票剩余:" + count); flag = true; } else { flag = false; } } } }
测试类不变
多个并发线程访问同一资源的同步代码块时 同一时刻只能有一个线程进入synchronized(this)同步代码块 当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定 当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)