线程的创建方法和介绍

线程的创建方法和介绍

  一个进程对应多个线程
   可以充分发挥COP性能的一个东西,一个进程至少有一个线程
   cpu 如何处理线程:单位时间片上高速的切换线程,并且一个单核的cpu值能处    理一个线程
   cpu的处理最小单位是线程,线程获取cpu的机会是一样的
   线程将一个独立的任务.包装成一块代码块,交给cpu 处理
    cpu决定分配资源给谁:线程的执行由cpu决定
    代码执行流程由cpu决定
    如果执行多个线程:
    看到的效果: 两个任务不规则的交替执行:

Threa类: Java中的线程类

run: 线程的线程体

需要包装任务,需要独立执行的代码块,

start: 启动线程的方法,告诉cpu,我准备好了.

第一种方法创建线程,继承Threa类,:

覆写run方法

要写几个类,根据功能的数量决定,定义线程类的数量

根据确定的功能,覆写run方法

创建线程对象,

调用start方法,启动线程

实例: 利用线程多个下载

cpu处理线程不一定马上分配资源,因为计算机有很多线程

期望看到的效果:交替不规则

public class Thread_2 extends Thread { //继承Thread类
   private String name;   //设一个字段 
    Thread_2(String name) {
        this.name = name;
    }
    @Override
    public void run() {  
        for (int i = 0; i < 100; i++) {
            System.out.println(name+"下载了" + i + "%");
        }
    }
}

测试:

public class Thread_1 {
    public static void main(String[] args) {
        System.out.println("打印一个单线程");
        Thread_2 thread_2=new Thread_2("金牌梅");   //启动线程的对象
        //thread_2.run();//只是调用方法而已,并不是线程
        thread_2.start();  //start 启动线程
        Thread_2 thread_21=new Thread_2("斗罗");
        thread_21.start();  //和第一个start交替

    }
}
斗罗下载了70%
金牌梅下载了81%
斗罗下载了71%
金牌梅下载了82%
斗罗下载了72%
金牌梅下载了83%
斗罗下载了73%
金牌梅下载了84%
斗罗下载了74%
金牌梅下载了85%
斗罗下载了75%
斗罗下载了76%
金牌梅下载了86%
斗罗下载了77%
金牌梅下载了87%
斗罗下载了78%
金牌梅下载了88%
斗罗下载了79%
金牌梅下载了89%
斗罗下载了80%
斗罗下载了81%
    交替不规则的效果

线程run方法作为线程的线程,必须覆写run方法:

上面方法还是不够完善,存在线程安全问题:

创建一个锁对象,可以被多个线程共享,相当于一个共享锁’

Object obj=new Object();

调用synchronized (obj) { 需要锁的数据 }

代码演示:

class Tic extends Thread   {
    private  static String name;
    static int tickets = 100;      //继承的字段,要共享.加static

  staic  Object obj = new Object();  //创建一个锁对象,可以被多个线程共享的的数据 ,必须共享锁

    public Tic(String name) {  //父类Thread也可以继承父类的(                                      (String name)
        this.name = name;
        //super(name);直接调用父类的
    }
    
    @Override  //必须覆写方法
    public void run() {
        while (true) {
            synchronized (obj) {
                if (tickets > 0) {
                    System.out.println(name + "卖出的座位是" + tickets--);

                } else {

                    break;
                }
            }
            try {
                Thread.sleep(100);                   //休眠时间  .自定义异常
            } catch (InterruptedException e) {
                e.printStackTrace();                     
            }

        }
        System.out.println(name + "票已经买完");            //
    }
}

调用start和调用run的区别;

调用start方法,就是启动一个线程,

线程一旦启动,就谁也管不了,只能由cpu分配. (每个线程都是独立的)

run方法里面只是一个普通方法;

run只是一个普通方法,也可以对象直接调用,

如果想要字段是共享的,字段必须static修饰,如果调用的是Runnable接口,

不需要用static 都是共享的,调用的就是一个线程对象,在Thread对象中去调用.

线程的第二种创建方式: 实现Runnable接口

run方法其实算是Runnable接口的,Thread也只不过调用,但是Runnable没有启动方法static的,所有使用接口覆写run方法还得启动,就只有new Thread对象作为一个可以放Runnable的壳.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jLiQTleL-1616227251595)(C:\Users\ljl\AppData\Local\Temp\1555909743633.png)]

首先看看下面的图解,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sqmxjTwf-1616227251596)(C:\Users\ljl\AppData\Local\Temp\1555904503817.png)]

代码详解:

class Runnable_11 implements Runnable {

    //String name;
    int num = 100;

  /* Runnable_11(String name){
       this.name=name;
   }*/

    @Override
    public void run() {
        while (num > 0) {
            if (num > 0) {
                System.out.println( "打印" + num);
                num--;
            }else {
                break;
            }
        }
    }
}

测试:

public class Runnable_1 {
    public static void main(String[] args) {
        Runnable_11 runnable_11 = new Runnable_11();
        Thread thread1 = new Thread(runnable_11,"第一");
        Thread thread2 = new Thread(runnable_11,"第二");
        Thread thread3 = new Thread(runnable_11,"第三");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

代码执行流程是独立的,但是对象是同一个,字段也是同一个,
每个线程访问的都是同个对象,同个字段,
实现的时候,不需要加static,所有字段都共享
继承:每个对象都是独立一份,
继承只能但几次,
接口:只需要创建一个对象,不需要static 就可以让字段共享
可以实现多个接口,
还可以继承想要的类

实现Runnable接口的线程同步

接口的线程同步的对象可以是this ,"" Object,

this表示当前对象,线程实现接口只创建一个对象,所有每次线程的对象都是一个

  1. 同步监听对象保证自身就是同步监听对象 //同步监听的基础条件
  2. 必须保证多个线程访问的对象都是同一个同步监听对象//同步监听的基础条件
  3. 同不监听对象可以是任意对象,再上面都满足的情况下
    4)this也可以是同步监听对象 (实现接口接口)
    5)当前类的字节码对象.class

代码实现:

class Runnable_11 implements Runnable {
    //String name;
    int num = 100;


    @Override
    public void run() {
        while (num > 0) {
            synchronized ("") {
                if (num > 0) {
                    //当前线程对象的引用 ....  获取名字
                    System.out.println(Thread.currentThread().getName() + "打印" + num);
                    num--;
                }
            }
        }
    }
}

​ 实现接口 写线程名字必须注意的的方法Thread.currentThread().getName():

获取当前线程对象的名字:

//当前线程对象的引用 ....  获取名字
System.out.println(Thread.currentThread().getName() + "打印" + num);

接口和基础的同步对象的区别

​ 代码执行流程是独立的,但是对象是同一个,字段也是同一个,

​ 每个线程访问的都是同个对象,同个字段,
实现的时候,不需要加static,所有字段都共享
继承:每个对象都是独立一份,
继承只能但几次,
接口:只需要创建一个对象,不需要static 就可以让字段共享
可以实现多个接口,
还可以继承想要的类

接口:同步代码块,可以是this 只有一个对象 ,可以" "字符串,

线程休眠

Thread.sleep(): 再指定线程内让线程处于休眠状态,

线程类Thread当中有一个static void sleep(long millis)方法,在指定的毫秒数内让当前正在执行的线程休眠

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ww1TQ7o8-1616227251598)(file:///C:\Users\ljl\AppData\Local\Temp\ksohtml6176\wps1.jpg)]

  1. 可以做倒计时:代码清单:

    Frame f = new Frame();
    		Label label = new Label("10");
    		label.setBackground(Color.RED);
    
    	// 字体对象
    		Font font = new Font("宋体",Font.BOLD,666);
    		label.setFont(font);
    		label.setAlignment(Label.CENTER);
    		f.add(label);
    		
    		f.setSize(780, 780);
    		f.setLocationRelativeTo(null);
    		f.setVisible(true);
    		
    		for (int i = 10; i >= 0; i--) {
    			label.setText(i+"");
    			Thread.sleep(1000)
    

    2.可以用来模拟网络延迟,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值