---恢复内容开始---
什么事多线程:
我们使用多线程 程序目的就是为了提高效率.
多线程程序相当于拥有多条通路去执行。
什么事进程:
可以简单理解成就是一个应用程序.
多个线程组成了一个进程.
进程与进程之间不可能进行通信,但是同一个进程中的线程可以进行通信.
线程的两种方式:
1.1 第一种是继承 Thread类,重写run方法
创建线程 创建我们自定义类的对象
启动线程 调用从Thread类中继承的start方法
/* 多线程是java中的一项技术 java中的多线程不是面向对象的。 java中怎样实现多线程(面试题) 首行知道:java.lang包下的所有类在使用时不需要导包. 1.java.lang.Thread 这个类就是java中的线程类. 阅读帮助文档 1.发现java中的线程有10个优先级,默认优行级为5.最高为10,最低为1 2.java中创建线程有两种方式 2.1 第一种是继承 Thread类,重写run方法 创建线程 创建我们自定义类的对象 启动线程 调用从Thread类中继承的start方法 */ /* 多线程程序的无规则性 根据这个程序的结果,发现main或run内容谁先执行,谁先执行多少个 这个是规律的,这个叫多线程程序的无序性. 为什么出现这种情况,是因为cpu在执行时,我们控制不了cpu的时间片 分配,分配给哪一个线程,哪个线程就执行。 */ /* 当我们执行这段代码时,一共有两个线程 一个是main线程, 另外一个是我们自定义的MyThread线程,我们管它叫子线程. */ class Demo2 { public static void main(String[] args) { MyThread mt=new MyThread();//创建线程对象 mt.start(); //启动线程 //mt.run(); //调用run方法 for(int i=0;i<100;i++){ System.out.println("main"+i); } } } /* 自定义一个线程类 步骤 1.继承Thread 2.重写run方法 通过查看帮助文档发现 Thread类中的run方法中没有任何内容,只是告诉我们子类要重写这个方法 3.创建线程对象,并启动线程 run方法作用: 要执行的子线程的内容。 start作用: 启动线程 jvm重新开辟运行通信 */ /* 调用run方法与start方法区别 start:使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 run:使用run方法执行,main方法中调用的run。 */ class MyThread extends Thread { //重写run方法 public void run(){ for(int i=0;i<100;i++){ System.out.println("run"+i); } //System.out.println("得写了从Thread类中继承的run"); } }
1.2 实现Runnable接口
Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。
/* 创建线程的第二种方式 2.2 实现Runnable接口 Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。 步骤 1.创建类去实现Runnable接口 2.Runnable接口中定义了一个run方法,必须重写 3.启动线程 将实现了Runnable接口类的对象做为参数传递给Thread构造方法, 这样在通过Thraed对象去调用start方法时,就知道应该执行哪个run。 例如 new Thread(实现Runnable接口对象).start(); */ class Demo3 { public static void main(String[] args) { Runnable mr=new MyRunnable(); //mr.start(); 不行,因为Runnable接口中没有定义start方法 //启动线程 Thread th=new Thread(mr); th.start(); //new Thread(mr).start(); /* 分析上面这句话 1.new Thread(mr) 通过这句话是不是知道 Thread类中提供一个可以接收Runnable类型的构造方法 2.通过帮助文档发现 参数的作用就是执行这个对象所对应的run方法 */ } } class MyRunnable implements Runnable { //重写接口中的方法 //使用实现接口 Runnable 的对象创建一个线程时, //启动该线程将导致在独立执行的线程中调用对象的 run 方法。 public void run(){ System.out.println("子线程执行的内容"); } } /* 启动线程 start方法 start方法是哪个类的 是Thread类中的。 */ /* 线程创建详细分析: 创建线程 就是Thread类对象. 实现这个Runnable接口,其实就是在定子线程中执行的内容。 要具体的想要创建线程,必须创建Thread为对象,那Runnable 接口中的run方法要想执行,要将其做为参数传递给Thread类. */
/* //第一种方式实现 MyThread mt=new MyThread(); mt.start(); 如果我们没有在自定义类中重写run方法,那么父类中run方法没执行任何内容 这不是我们想要的,我们只有在自定义类中重写run,完成我们想要的功能 */ /* //第二种实现 MyRunnable mr=new MyRunnable(); new Thread(mr).start(); 这时调用的是我们实现Runnable接口中的run方法的内容. */
1.3 怎样创建多个子线程
2.Thread类中常用的方法
1.String getName() 得到线程的名字
2.void setName() 设置线程的名称
3.static Thread currentThread() 得到当前正在运行的线程的对象的引用
4.了解 String toString() 线程对象的字符串表示形式 包括 线程名 优先级 线程组。
创建线程两种方式
1. extends Thread
2. implements Runnable
所有的线程都有名字
class Demo4 { public static void main(String[] args) { //怎样创建多个子线程 /*创建三个线程,分别执行a,b,c,三个方法*/ ThreadDemo td1=new ThreadDemo(); ThreadDemo td2=new ThreadDemo(); ThreadDemo td3=new ThreadDemo(); td1.setName("a"); td2.setName("b"); td3.setName("c"); //System.out.println(td1.getName()); //System.out.println(td2.getName()); //System.out.println(td3.getName()); td1.start(); //a //td2.start(); //b //td3.start(); //c } } class ThreadDemo extends Thread { public void run(){ /* 怎样能知道是哪个线程 */ //System.out.println("子线程内容"); //判断线程的名称,来调用相应的方法 //System.out.println(this.getName()); Thread th=Thread.currentThread(); //th代表的是当前正在执行的线程对象的引用 String threadName=th.getName(); if("a".equals(threadName)){ a(); } if("b".equals(threadName)){ b(); } if("c".equals(threadName)){ c(); } } public void a(){ System.out.println("a method"); } public void b(){ System.out.println("b method"); } public void c(){ System.out.println("c method"); } }
1.4 实现 Runnable接口
class Demo5 { public static void main(String[] args) { /*怎样创建多个线程对象*/ ThreadDemo td1=new ThreadDemo(); //ThreadDemo td2=new ThreadDemo(); //ThreadDemo td3=new ThreadDemo(); Thread th1=new Thread(td1); Thread th2=new Thread(td1); Thread th3=new Thread(td1); /*给线程起名*/ th1.setName("a"); th2.setName("b"); th3.setName("c"); th1.start(); th2.start(); th3.start(); } } class ThreadDemo implements Runnable { public void run(){ //System.out.println("子线程执行的内容"); String name=Thread.currentThread().getName(); if(name.equals("a")){ a(); } if("b".equals(name)){ b(); } if("c".equals(name)){ c(); } } public void a(){ System.out.println("a method"); } public void b(){ System.out.println("b method"); } public void c(){ System.out.println("c method"); } }
关于创建线程的两种方式区别
建议使用哪一个
1.extends Thread
2.implements Runnable
建议使用第二种,为什么?
1.java中支持多实现,而不支持多继承。
如果使用了继承,那么我们程序的可扩展性下降,因为一个类只能有一个父类
使用实现,我们可以实现多个接口,不影响我们程序的扩展性。
2.关于数据共享
2.1如果使用继承Thread类来实现数据共享,那么这个数据要static,
它的生命周期太长.
2.2如果使用实现Runnable,这时候只需有一个实现Runnable对象将其传递给
Thread类的构造方法,就可以实现多个线程操作同一个数据。
class Demo6 { public static void main(String[] args) throws Exception { /* ThreadDemo td1=new ThreadDemo(); ThreadDemo td2=new ThreadDemo(); ThreadDemo td3=new ThreadDemo(); td1.start(); td2.start(); td3.start(); */ /* 以上是三个线程对象,它们内部都有自己的成员属性id。 如果我们想要让这三个线程操作的是同一个数据id,应该怎么办? 如果使用继承Thread类来实现数据共享,那么这个数据要static, 它的生命周期太长. */ ThreadDemo td=new ThreadDemo(); Thread th1=new Thread(td); Thread th2=new Thread(td); Thread th3=new Thread(td); //Thread.sleep(10);//使用时注意抛出异常 th1.start(); Thread.sleep(10);//使用时注意抛出异常 System.out.println(td.id); //Thread.sleep(10);//使用时注意抛出异常 th2.start(); Thread.sleep(10);//使用时注意抛出异常 System.out.println(td.id); //Thread.sleep(10);//使用时注意抛出异常 th3.start(); Thread.sleep(10);//使用时注意抛出异常 System.out.println(td.id); } } /* class ThreadDemo extends Thread { static int id=10; public void run(){ id++; } } */ class ThreadDemo implements Runnable { int id=10; public void run(){ id++; } }
多线程程序的几种状态
/* 多线程程序的几种状态 1.创建状态 2. start 启动 运行状态 3.冻结 4.销毁 1. 线程结束 run运行结束 2.调用stop()不建议使用 5.临时堵塞状态 */ class Demo7 { public static void main(String[] args) { ThreadDemo td=new ThreadDemo(); Thread th1=new Thread(td); Thread th2=new Thread(td); th1.start(); //运行 th2.start(); //运行 //new Thread(td).start(); //运行 //System.out.println("main message"); } } class ThreadDemo implements Runnable { public void run(){ /* System.out.println("hello"+Thread.currentThread().getName()); try{ Thread.sleep(10); //冻结 }catch(Exception e){ } System.out.println("world"+Thread.currentThread().getName()); */ for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()); } } }
撒旦法说生的
---恢复内容结束---