JAVA多线程基础:基础语法

  • 线程运行速度比进程速度快

实现多线程的3种方案

可以实现Thread类

  • 任何情况下,只要定义了多线程,多线程的启动永远只有一种方案,Thread类中的start()方法

  • 内部调用的是strat0(),这是一个JNI实现方法,JVM根据不同的系统实现不同的start0()方法

    import java.util.function.*;
    class MyThread extends Thread{
    	private String title;
    	public MyThread(String title){
    		this.title = title;
    	}
    	@Override
    	public void run(){
    		for(int i= 0;i< 10;i++){
    			System.out.println(this.title + "i = " + i);
    		}
    	}
    }
    public class JavaDemo{
        public static void main(String[] arges){
            MyThread myThread01 = new MyThread("TEST01 ");
    		myThread01.start();
            MyThread myThread02 = new MyThread("TEST02 ");
    		myThread02.start();
            MyThread myThread03 = new MyThread("TEST03 ");
    		myThread03.start();
        }
    }
    

    Runnable实现多线程

  • 1.8之后就变为函数式接口,可以直接实现lambda函数式

  • 开发中首要考虑Runnable实现,并通过Thread.start()方法

  • 借助构造方法:public Thread(Runnable target)实现

    • 这里是实现接口,所以MyThread可以作为一个正常的类,去继承其他类或是实现多个接口
import java.util.function.*;
class MyThread implements Runnable{
	private String title;
	public MyThread(String title){
		this.title = title;
	}
	@Override
	public void run(){
		for(int i= 0;i< 10;i++){
			System.out.println(this.title + "i = " + i);
		}
	}
}
public class JavaDemo{
    public static void main(String[] arges){
        Thread thread = new Thread(new MyThread("TEST"));
		thread.start();
    }
}
  • Lambda函数式(超简洁)

    public class JavaDemo{
        public static void main(String[] arges){
    		Runnable run = ()->{
    			System.out.println("这里在多线程中执行");
    		};
            new Thread(run).start();
        }
    }
    
#更简单的
import java.util.function.*;
public class JavaDemo{
    public static void main(String[] arges){
        new Thread(()->{
			System.out.println("dsfsdf");
		}).start();
    }
}
Thread与Runnable的关系
  • ````public class Thread extends Object implements Runnable{}```Thread类也是实现了Runnable接口的子类
  • 有上面了解到,多线程的方法主要都是由Thread实现的,所以操作系统的资源调用也是通过Thread调用的
  • Thread为代理类,MyThread或者实现Runnable接口的类为真实类
  • 多线程开发的本质是在于多个线程可以进行对统一资源的抢占

Callable实现多线程

  • Runnable的缺点是,执行完毕后,无法给主线程一个返回值

  • 1.5之后实现的新方法java.util.concurrent.Callable接口,使用泛型返回数据

  • 方法流程图

在这里插入图片描述

Runnable与Callable
  • Runnable是在JDK1.0的时候提出的多线程的实现接口,而Callable是JDK1.5之后提出来的

  • java.lang.Runnable接口之中只提出一个run()方法,并没有返回值

  • java.util.concurrent.Callable接口提供有call()方法,可以有返回值;

    import java.util.concurrent.Callable;
    import java.util.concurrent.FutureTask;
    
    class MyThread implements Callable<String>{
    	@Override
    	public String call() throws Exception{
    		for(int i=0;i < 1000;i++){
    			System.out.println("==========" + i);
    		}
    		return "=====end========";
    	}
    }
    public class JavaDemo{
        public static void main(String[] arges)throws Exception{
            FutureTask<String> task = new FutureTask<>(new MyThread());
    		new Thread(task).start();
    		System.out.println(task.get());
        }
    }
    

其他小知识

多线程的状态

状态
  • 创建
  • start()
    • 就绪状态
      • 阻塞状态
    • 运行状态
  • 终止
进程与休眠
  • 一个程序中可以启动若干个JVM,每个JVM就是一个进程
  • 休眠可以设置为毫秒和纳秒2中精确度,如果被打断会抛出Exception子类的异常,必须处理
  • 所有线程运行同一个方法时,也会有先后,并没有绝对的一起执行

线程的名称

  • 开发为了获得一些线程的操作,可以通过线程的名称获得

    • 构造方法:public Thread(Runnable target,String name)
    • 设置名称:public final void setName(String name)
    • 取的名称:public final String getName();
    • 获得当前线程的方法:Thread.currentThread().getName()

线程中断

  • 判断是否被中断:public boolean isInterrupted();//被中断 返回true
  • 中断线程执行:public void interrupt();

线程的强制执行

public class test {

    public static void main(String[] args) {
       Thread mainThread = Thread.currentThread();
       Thread thread = new Thread(()->{
           for (int x = 0; x < 100; x++){
               if (x == 3){
                   try {
                       mainThread.join();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
               System.out.println("thread == " + x);
           }
       });
        thread.start();
        for (int i = 0; i < 100; i++){
            System.out.println("霸道主线程mainThread == " + i);
        }
    }
}

线程的礼让

  • 礼让:public void yield()

  • 每次出现竞争的时候,都会礼让一次,大部分时候会礼让,但是不明显

      public static void main(String[] args) {
           Thread thread = new Thread(()->{
               for (int x = 0; x < 100; x++){
                   if (x % 3 == 0){
                       Thread.yield();
                       System.out.println("===========我礼让一次===========");
                   }
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println("thread == " + x);
               }
           });
            thread.start();
            for (int x = 0; x < 100; x++){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("霸道主线程mainThread == " + x);
            }
        }
    

优先级设置

  • 设置优先级:public final void setPriority(int new Priority);
    • 默认优先级: 5(NORM_PRIORITY)
    • 最高优先级:MAX_PRIORITY 10
    • 中等优先级:NORM_PRIORITY 5
    • 最低优先级:MIN_PRIORITY 1
  • 获取优先级:public final int getPriority()

同步方法

同步代码块、同步方法

  • 同步代码块,速度会变慢

线程的等待机制

  • 死等:wait()
  • 设定等待时间 wait(long timeout,int nanos)
  • 唤醒第一个等待线程:notify()
  • 唤醒全部线程:notifyALL()
  • 禁用的方法:stop()、suspend()挂起、destroy()销毁
  • 用全局变量去停止线程

守护线程

- 设置守护线程:public final void setDaemon(boolean on);
- 判断是否为守护线程:public final boolean isDaemon();
- 设置为守护线程后,整体程序结束后,守护线程也将结束
- JVM最大的守护线程就是GC线程,程序结束,GC也一起结束

volatile

正常的变量处理步骤:
  • 获取变量原有的数据内容副本
  • 利用副本为变量进行数学计算
  • 将计算后的变量,保存到原始空间之中
volatile关键字
  • 表示不使用副本,而是直接操作变量,所以并不是同步操作,也需要同步关键字
volatile与syncharoniaed的区别
  • volaile主要在属性上使用,而synchronized是在代码块与方法上使用的
  • volatile无法描述同步的处理,它只是一种直接内存的处理,避免的副本的操作,而synchronized是实现同步的
  • volatile配送syncharoniaed处理同步,可以更快的运行

StringBuffer

  • 线程安全的字符串添加方法,1.0之后提供的

  • 追加:new StringBUffer(“www.cn”).insert(4,“mldn”)在第4个开始追加

  • 部分删除:buf.append(“www.mldn.com”).delete(4,8).insert(4,“bridge”);//“www.bridge.com”

  • 支付反转:buf.reverse()

  • StringBuilder:非线程安全的效率更高,1.5之后才提供的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章