高并发与多线程网络学习笔记(一)Tread线程特点和线程生命周期

进程和线程的区别

  • 进程是资源分配的最小单位,线程是CPU调度的最小单位
  • 进程是一个资源的容器,为进程里的所有线程提供共享资源,是对程序的一种静态描述,(例如:可以把一个应用看成是一个进程,PS:部分应用还有一个守护进程),对于单个(与单核不是一个概念)CPU来说,一个时刻只能运行一个进程,进程之间可以相互切换。
  • 线程是计算机最小的调度和运行单位,是对程序的一种动态描述,一个进程中可以包含多个线程(各个线程是独立的)。
  • 一静一动,正好组成了完整的程序
  • 注意:CPU的核数和线程数是正相关的,四核cpu可以同时运行四个线程
    线程的生命周期
    注意:当Java虚拟机启动时,一定会创建一个main线程(非守护线程),main线程会被jvm调用。jvm启动时除了会创建main线程,还会创建多个的守护线程,比如垃圾回收器和句柄线程。
    在这里插入图片描述
    创建线程的方式
    一、继承Thread类创建线程类

(1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。

(2)创建Thread子类的实例,即创建了线程对象(如果只是创建了线程对象而没有启动线程,此时的线程对象不能称为线程)。

(3)调用线程对象的start()方法来启动该线程。

注意:只是创建线程对象,在没有调用start()方法之前,不能称之为一个线程,并且start()会立即返回。

    public class threaTest {
      public static  void main(String[] args){
         new Thread("Read-Thread"){
            public void run(){
                readDataBase();
            }
          }.start();//创建匿名内部类,内部类可以调用外部类的方法readDataBase()
          
          new Thread("Write-Thread"){
              public void run(){
                  writeFile();
              }
          }.start();
      }

    private  static void readDataBase(){
        try {
            println("Begin read data");
            Thread.sleep(1000);
            println("Read data done");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        println("handle finish");
    }
    private static void  writeFile(){
        try {
            println("Begin write data");
            Thread.sleep(2000);
            println("write data done");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        println("write finish");
    }
   public static void println(String message){
        System.out.println(message);
   }
}

运行结果:

Begin read data
Begin write data
Read data done
handle finish
write data done
write finish

通过将变量定义成static实现Thread子类的变量共享

public class thread2 extends Thread {
     private final String name;
     private static  final int Max=10;
     private static int index=1;

     public thread2(String name){
         this.name=name;
     }
     @Override
     public void run(){
         while(index<=Max){

             System.out.println(name+":"+index++);
         }

  }
  
}
public class thread2Test {
    public static void main(String[] args){
        thread2 t1=new thread2("一号柜台:");
        t1.start();
        thread2 t2=new thread2("二号柜台:");
        t2.start();

    }
}

运行结果:

一号柜台::1
一号柜台::2
一号柜台::3
一号柜台::4
一号柜台::5
一号柜台::6
一号柜台::7
二号柜台::1
二号柜台::9
二号柜台::10
一号柜台::8

线程的构造函数

//若不重写run方法或传递runnable对象,则不会运行逻辑,如果没有指定线程名,默认线程名‘Thread-计数’。Thread可以直接被实例化,但是run()方法是空的,具体初始化过程参考init()方法。
Thread()
//指定线程名,默认线程名‘Thread-计数’
Thread(String name)

//传递Runnable接口对象,如果在构造Thread的时候没有传递Runnable或者没有复写Thread的run方法,该Thread将不会调用任何东西,如果传递了Runnable接口的实例或者复写了Thread的run方法,则会执行相应的逻辑代码。
Thread(Runnable target)

//指定线程名,默认线程名‘Thread-计数’
Thread(Runnable target, String name)

//线程组是为了更好的统一对线程管理,比如同时关闭组内所有线程
//如果构造线程对象时未传入ThreadGroup,Thread会默认获取父线程(调用当前线程start()方法的线程)的ThreadGroup作为该线程的ThreadGroup。此时子线程和父线程在同一个ThreadGroup。可以利用ThreadGroup查看该ThreadGroup一共有多少线程在执行。
Thread(ThreadGroup group, Runnable target)
//Allocates a new Thread object.指定线程组,默认线程组为父线程的组
Thread(ThreadGroup group, Runnable target, String name)
//Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group.
//stacksize代表该线程占用的stack的大小,是指线程占用的栈深(递归溢出的大小),影响每一个线程可以进行的压栈次数(类似于一个线程递归调用中递归的次数),栈深越大,栈内线程可用数越少,受操作系统影响,有些平台上未必有用
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
//Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group, and has the specified stack size.

Thread(ThreadGroup group, String name)
//Allocates a new Thread object.

实现数据共享的方式二
利用Runable,将业务的共享数据抽取出来,作为多个线程的target
Runnable接口创建线程类

(1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

(2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

(3)调用线程对象的start()方法来启动该线程。

这种方法运用了模板策略:

定义一个算法流程的骨架,把一些可变节点延迟到具体的子类中去执行

把逻辑实例和线程分开,每个线程共享同一个逻辑,是一种有效减少程序中类的数量的开发模式

public class TicketWindowRunable implements  Runnable{
    private static  final int Max=10;
    private static int index=1;
     public void run(){

         while(index<=Max){

           System.out.println(Thread.currentThread()+":"+index++);
         }
     }
}
public class thread2Test {
    public static void main(String[] args){
    final  TicketWindowRunable target=new TicketWindowRunable();
    //多线程共享target
    Thread t1=new Thread(target,"一号");
    t1.start();
    Thread t2=new Thread(target,"二号");
    t2.start();

    }
}

运行结果:

Thread[二号,5,main]:1
Thread[二号,5,main]:3
Thread[二号,5,main]:4
Thread[二号,5,main]:5
Thread[二号,5,main]:6
Thread[二号,5,main]:7
Thread[二号,5,main]:8
Thread[二号,5,main]:9
Thread[一号,5,main]:2
Thread[一号,5,main]:10
Thread[二号,5,main]:11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值