1.实现多线程

1.1进程
进程:是正在运行的程序
是系统进行资源分配和调用的独立单位
每一个进程都有它自己的内存空间和系统资源
1.2线程
线程:是进程中的单个顺序控制流,是一条执行路径
单线程:一个进程如果只有一条执行路径,则称为单线程程序
多线程:一个进程如果有多条执行路径,则称为多线程程序
1.3多线程的实现方式

方式1:继承Thread类
定义一个类MyThread继承Thread类 在MyThread类中重写run()方法
创建Mythread类的对象 启动线程

为什么重写run()方法?
因为run()是用来封装被线程执行的代码
run()方法和start()方法的区别?
run():封装线程执行的代码,直接调用,相当于普通方法的调用
start():启动线程;然后由JVM调用此线程的run()方法

例:

package smile1;
import java.util.*;

public class caogao {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        //若直接my1.run()调用和普通方法调用相同,启动多线程应当用start
        my1.start();
        my2.start();
    }
}
class MyThread extends Thread{
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println(i);
        }
    }
}

方式2:实现Runnable接口
定义一个类MyRunnable实现Runnable接口
在MyRunnable类中重写run()方法
创建MyRunnable类的对象
创建Thread类的对象,把MyRunnable对象作为构造方法的参数
启动线程

例:

package smile1;
import java.util.*;
public class caogao {
    public static void main(String[] args) {
        //创建MyRunnable类的对象
        MyRunnable my=new MyRunnable();
        //注意该接口中只有run方法,没有start方法
        //所以可以通过thread类对实现这个线程的类进行一个封装,封装为Thread类
        //创建Thread类的对象,把MyRunnable对象作为构造方法的参数,创建两个线程
        //Thread (Runnable targer)
        Thread t1=new Thread(my);
        Thread t2=new Thread(my);
        //启动线程
        t1.start();
        t2.start();
    }
}
class MyRunnable implements Runnable{
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
     //System.out.println(getName()+":"+i);这样写会报错
// 不能直接用getName()方法,因为它是Thread类的方法,而MyRunnable实现的是Runnable接口
        }
    }
}

另外,当创建多线程的同时又要给线程名字赋值时

//Thread (Runnable targer,String name)创建多线程的同时又给线程名字赋值
        Thread t3=new Thread(my,"一");
        Thread t4=new Thread(my,"二");

Java应用进程号Linux_开发语言

1.4设置和获取线程名称
Thread类中设置和获取线程名称的方法
void setName(String name):将此线程的名称更改为等于参数name
String getName():返回此线程的名称

如何获取main()方法所在的线程名称?
public static Thread currentThread():返回对当前正在执行的线程对象的引用

返回默认线程名称

package smile1;
import java.util.*;

public class caogao {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        //若直接my1.run()调用和普通方法调用相同,启动多线程应当用start
        my1.start();
        my2.start();
    }
}
class MyThread extends Thread{
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println(getName()+":"+i);
            //Thread-1:36
            //Thread-0:16
            //Thread-1:37
            //Thread-0:17
        }
    }
}

利用setName()方法更改线程名称

package smile1;
import java.util.*;

public class caogao {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        //若直接my1.run()调用和普通方法调用相同,启动多线程应当用start
        my1.setName("gaotie");
        my2.setName("feiji");
        my1.start();
        my2.start();
        //gaotie:53
        //feiji:70
        //feiji:71
        //gaotie:54

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

带参构造方法给name赋值,更改线程名称
构造带参构造方法,并需要通过super访问父类带参构造方法 super(name);

package smile1;
import java.util.*;

public class caogao {
    public static void main(String[] args) {

        MyThread my1=new MyThread("gaotie");//通过构造方法给name赋值
        MyThread my2=new MyThread("feiji");

        my1.start();
        my2.start();
        //gaotie:53
        //feiji:70
        //feiji:71
        //gaotie:54

    }
}
class MyThread extends Thread{
    public MyThread(){}//无参构造方法
    public MyThread(String name){//带参构造方法,并需要通过super访问父类带参构造方法
        super(name);
    }
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println(getName()+":"+i);
        }
    }
}

返回当前正在执行main方法的线程的名称

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

1.5线程调度

Java应用进程号Linux_jvm_02

package smile1;
import java.util.*;

public class caogao {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        MyThread my3=new MyThread();
        my1.setName("no.1");
        my2.setName("no.2");
        my3.setName("no.3");
        
        //查看优先级范围
        System.out.println(Thread.MAX_PRIORITY);//最大优先级10
        System.out.println(Thread.MIN_PRIORITY);//最小优先级1
        System.out.println(Thread.NORM_PRIORITY);//默认优先级5

        //设置优先级
        my1.setPriority(1);
        my2.setPriority(5);
        my3.setPriority(10);

        //获取线程优先级
        System.out.println(my1.getPriority());//1
        System.out.println(my2.getPriority());//5
        System.out.println(my3.getPriority());//10

        my1.start();
        my2.start();
        my3.start();
        
    }
}
class MyThread extends Thread{
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println(getName()+":"+i);
        }
    }
}

1.6线程控制

线程控制的三个方法

Java应用进程号Linux_java_03


第一个函数sleep

package smile1;
import java.util.*;

public class caogao {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        MyThread my3=new MyThread();
        my1.setName("no.1");
        my2.setName("no.2");
        my3.setName("no.3");

        my1.start();
        my2.start();
        my3.start();
    }
}
class MyThread extends Thread{
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println(getName()+":"+i);
            
            //每输出一次后让线程休眠1秒钟
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

输出

no.1:0
no.3:0
no.2:0
no.1:1
no.3:1
no.2:1
......

示例2:

package smile1;
import java.util.*;
import java.util.concurrent.*;

public class caogao {
    public static void  main(String[] args){
        Test t=new Test();
        Thread t1=new Thread(t,"测试1");//需要封装
        t1.start();
    }
}
class Test implements Runnable{
    public void run(){
        long s=System.currentTimeMillis();//把系统当前的时间转变为毫秒,很大用long
        System.out.println("开始了");
        try {
            Thread.sleep(2000);
            //可能出现等待时间过长超出2000出现异常,由于run不能抛出异常,故必须try...catch...处理
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束");
        System.out.println("用时:"+(System.currentTimeMillis()-s));
    }
}
//开始了
//结束
//用时:2009

第二个函数join

package smile1;
import java.util.*;

public class caogao {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        MyThread my3=new MyThread();
        my1.setName("no.1");
        my2.setName("no.2");
        my3.setName("no.3");

        my1.start();
        try {
            my1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //第一个函数执行完以后再执行后面的

        my2.start();
        my3.start();
    }
}
class MyThread extends Thread{
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println(getName()+":"+i);
        }
    }
}

第三个函数setDaemon

package smile1;
import java.util.*;
public class caogao {
    public static void main(String[] args) {
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        MyThread my3=new MyThread();
        my1.setName("保镖1");
        my2.setName("保镖2");

        //设置主线程
        Thread.currentThread().setName("主线程");

        //设置守护线程
        my1.setDaemon(true);
        my2.setDaemon(true);

        my1.start();
        my2.start();
        for(int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }

        //这样当主线程死亡的时候,守护线程也会马上死亡
    }
}
class MyThread extends Thread{
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println(getName()+":"+i);
        }
    }
}

1.7线程生命周期

Java应用进程号Linux_jvm_04


增加:

一.

1.线程的第三种创建模式

package smile1;
import java.util.*;
import java.util.concurrent.*;

public class caogao {
   public static void main(String[] args) {
       T3 t=new T3();
       //在测试中创建工具类,首先告诉可以从t中取得相应值,并且还实现了线程相应的接口
       FutureTask<Integer> futuret=new FutureTask<Integer>(t);
       Thread th=new Thread(futuret,"线程一");
       Thread th2=new Thread(futuret,"线程二");
       //当futuret需要获取返回值时只能有一个线程执行,故第二句话不会执行
       th.start();//线程只是启动了,还没获取,futuret这个工具类还可以做结果的获取
       try {
           System.out.println(futuret.get());//获取返回值内容,但是由于可能等待时间过长,故而需要对返回值处理,异常处理或者抛出
       } catch (InterruptedException e) {
           e.printStackTrace();
       } catch (ExecutionException e) {
           e.printStackTrace();
       }
       //futuret两个能力,线程接口能力,取得返回值能力
   }
}
class T3 implements Callable<Integer>{//实现Callable接口,并实现call方法的重写
    public Integer call() throws Exception{
        System.out.println(Thread.currentThread().getName());
        int sum=0;
        for(int i=1;i<11;i++)
            sum+=i;
        return sum;
    }
}
//线程一
//55

2.以匿名的方式完成线程的启动
匿名方式的Thread类

package smile1;
import java.util.*;
import java.util.concurrent.*;

public class caogao {
   public static void main(String[] args) {
      new Thread(){
          public void run(){
              System.out.println("匿名线程");
          }
      }.start();
   }
}
//匿名线程

匿名方式的Runnable接口

package smile1;
import java.util.*;
import java.util.concurrent.*;

public class caogao {
   public static void main(String[] args) {
      new Thread(new Runnable() {//匿名实现接口并创建匿名类
          @Override
          public void run() {//接口的方法重写
              System.out.println("匿名线程2");
          }
      }).start();
   }
}
//匿名线程2

3.lambda表达式线程创建

package smile1;
import java.util.*;
import java.util.concurrent.*;

public class caogao {
   public static void main(String[] args) {
      new Thread(()->{System.out.println("lambda线程3");}).start();

   }
}
//lambda线程3

4.做线程类的测试工作

package smile1;
import java.util.*;
import java.util.concurrent.*;

public class caogao extends Thread{
   public static void main(String[] args) {
       caogao test=new caogao();//做线程类的测试工作,该测试类本身就具有线程类的能力
       test.start();
   }
   public void run(){
       System.out.println("线程测试");
   }
}
//线程测试
package smile1;
import java.util.*;
import java.util.concurrent.*;

public class caogao implements Runnable{
   public static void main(String[] args) {
       caogao test2=new caogao();//做线程类的测试工作,该测试类本身就具有线程类的能力
       Thread t=new Thread(test2);
       t.start();
   }
   public void run(){
       System.out.println("线程测试2");
   }
}
//线程测试2

5.yield()让步方法

package smile1;
import java.util.*;
import java.util.concurrent.*;

public class caogao {
    public static void  main(String[] args){
        Test t=new Test();
        Thread t1=new Thread(t,"测试1");
        t1.start();
        Thread t2=new Thread(t,"测试2");
        t2.start();
        t1.yield();//只让出一次,下次可能又从就绪态变成运行态,并非一直在让步
    }
}
class Test implements Runnable{
    public void run(){
        for(int i=1;i<101;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

6.线程同步-volatile

package smile1;
import java.util.*;
import java.util.concurrent.*;

public class caogao extends Thread{
    //public static boolean stop=false;
    public volatile static boolean stop=false;
    public void run(){
        System.out.println("开始");
        while(!stop){

        }
        System.out.println("结束");
    }
    public static void  main(String[] args) throws InterruptedException {
        caogao t=new caogao();
        t.start();
        Thread.sleep(1000);
        t.stop=true;
        /*当public static boolean stop=false;
        尽管主线程已经修改了stop的值,输出仍然是停留在“开始”,因为线程依然访问的是副本*/

        /*当public volatile static boolean stop=false;输出变为“开始  结束”
        关键词volatile,可以让当某一个线程修改共享变量修改完后通知其他线程重新读取该变量*/
    }
}