java线程初级

emmmm…

不知不觉已经学到了线程了 没写过博客 不过很多人都推荐写博客 所以就试试喽

1.线程实现的方式

1.继承Thread类

废话不说先上例子

public class Demo1 {
    //首先在类中方法外定义一个静态类使其继承Thread
    static class MyThread extends Thread {
        @Override
       //覆写Thread中的run方法
        public void run() {
            for (int i = 0; i < 10; i++) {//使用一个10次的循环
                System.out.println("这是第" + (i + 1) + "次执行");//输出第几次执行
            }
        }
    }
    public static void main(String[] args) {
        new MyThread().start();//启动线程
    }
}

启动线程得到结果

这是第1次执行
这是第2次执行
这是第3次执行
这是第4次执行
这是第5次执行
这是第6次执行
这是第7次执行
这是第8次执行
这是第9次执行
这是第10次执行

程序中我们可以清晰的看到是一个类继承自Thread,那么我们知道继承的父类只能有一个,当我们继承自Thread后就无法继承别的类或者是我们继承自一个类就无法继承Thread那么java开发者又给了我们一种选择就是Runnable接口

2.实现Runnable接口

打开Runnable类的源代码我们可以看到Runnable接口中只定义了一个run方法 所以我们在实现Runnable接口时只需要覆写run方法

public class Demo1 {
    //创建MyRunnable实现Runnable接口
    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {//使用一个10次的循环
                System.out.println("这是第" + (i + 1) + "次执行");//输出第几次执行
            }
        }
    }
    public static void main(String[] args) {
        //创建MyRunnable对象
        MyRunnable myRunnable = new MyRunnable();
        //创建线程
        new Thread(myRunnable).start();
    }
}

2.线程操作

1. 线程休眠

使用sleep时无法抛出异常只能用try catch捕捉

 Thread.sleep(1000);//执行线程休眠方法
 try {
      Thread.sleep(1000);
  } catch (InterruptedException e) {
        e.printStackTrace();
  }

2.线程放弃

使当前线程主动放弃时间片

Thread.yield();//线程主动放弃时间片
当创建两个线程后输出结果:
这是第1次执行Thread-0
这是第1次执行Thread-1
这是第2次执行Thread-0
这是第2次执行Thread-1
这是第3次执行Thread-0
这是第3次执行Thread-1
这是第4次执行Thread-0
这是第4次执行Thread-1
这是第5次执行Thread-0
这是第5次执行Thread-1
这是第6次执行Thread-0
这是第6次执行Thread-1
这是第7次执行Thread-0
这是第7次执行Thread-1
这是第8次执行Thread-0
这是第8次执行Thread-1
这是第9次执行Thread-0
这是第9次执行Thread-1
这是第10次执行Thread-0
这是第10次执行Thread-1

可以看出输出的结果呈很明显的交叉分布

3.线程加入

允许其他线程加入到当前线程中

thread.join();//当前线程加入主线程

当一个线程调用join方法时,该线程阻塞其他线程的执行,当该线程运行完毕之后其他线程才会执行,但该线程必须调用启动方法

当存在两个线程调用join方法时这两个线程依旧会抢占执行,然后等这两个线程执行完毕之后其他线程才会执行

4.设置线程优先级

线程优先级Priority

t1.setPriority(6);//设置线程优先级
  • 首先线程优先级分为1-10共有10个等级
  • 我们在启用start而不设置线程优先级的时候默认的优先级为5
t1.join();
t1.setPriority(9);//这样写会失去效用
  • join和设置线程优先级不能同时使用否则会失去效用即join的阻塞效果以及线程的优先效果都会失去
t2.join();
t1.setPriority(9);
  • 当两个线程一个调用join 一个设置线程优先级 则线程也是抢占执行
  • 在这里两个join与setPriority都是抢占执行 why?

5.设置守护线程

  • 守护线程是和主线程(用户线程)一起结束的线程
  • 首先守护线程会随着主线程的结束而强制结束(无论守护线程有没有执行完毕)
t1.setDaemon(true);//将t1设置为守护线程

6.线程锁的使用

同步代码块

  • 当我们运行线程的时候 有些情况:例如在上一个线程还没有结束的时候下一个线程已经开始执行,而上一个线程的执行结果会影响到下一个线程的数据,此时就会出现线程安全问题,在这种情况之下我们就引进了线程锁

  • static class MyThread implements Runnable{
        //首先创建锁
        private Object obj = new Object();
        private int i = 100;
        @Override
        public void run() {
            //加入同步块
            while(true){
                //这里就是同步代码块
                synchronized(obj){
                if (i<=0) {
                    break;
                }
                    System.out.println();
                    i--;
               }
           }
        }
    }
    
  • 在这里介绍的只是synchronized锁的一个应用 也是性能相对较高的应用方式

  • 当然synchronized锁也可以使用在静态方法上

  • 也可以使用在实例方法中

同步静态方法

public class Demo2 {
    static class MyThread implements Runnable {
        private static int n=100;
        //创建synchronized锁修饰的静态方法
        public static synchronized void cls() throws InterruptedException {

            for (int i=0;i<100;i++) {
                Thread.sleep(200);
                n--;            System.out.println(Thread.currentThread().getName()+"............."+n);
            }
        }
        @Override
        public void run() {
            try {
                MyThread.cls();//调用被synchronized修饰的静态方法
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        //创建两个线程进行测试
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        Thread t1 = new Thread(myThread1);
        Thread t2 = new Thread(myThread2);
        t1.setName("线程1");
        t2.setName("线程2");
        t2.start();
        t1.start();
    }
}
  • 运行此程序 也就是利用synchronized锁修饰的静态方法
  • synchronized修饰静态方法相当于锁的是当前类也就是相当于synchronized(MyThread.class)
  • 由于锁的是 MyThread 类所以无论你创建了多少个这个类的对象 无论线程执行的是哪个对象当我们执行线程的时候都会线程安全
  • 通过结果分析到当调用start方法t2 t1抢时间片 当一个线程抢到时间片另一个线程就会被synchronized锁阻塞待 这个线程执行完毕另一个线程才会执行
  • 也就是说当synchronized锁应用在静态方法上时且线程的作用区间是这个类的类对象 会限制单个线程运行

同步方法

public class Demo1 {
    private static int i=100 ;
    static class MyThread implements Runnable{

        public synchronized void cls(){//synchronized锁普通类
            for (int n =0;n<50;n++) {
               if (i<=0)break;
                System.out.println(Thread.currentThread().getName()+"......"+i);
            i--;
            }
        }
        @Override
        public void run() {
            cls();
        }
    }
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();

        Thread t1 = new Thread(myThread1);
        Thread t2= new Thread(myThread1);
        Thread t3 = new Thread(myThread1);

        t1.setName("线程1");
        t2.setName("线程2");
        t3.setName("线程3");

        t1.start();
        t2.start();
        t3.start();
    }
}

当我们新建一个MyThread对象的时候

  MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        
        Thread t1 = new Thread(myThread1);
        Thread t3 = new Thread(myThread2);
        
        t1.setName("线程1");
        t3.setName("线程3");

        t1.start();
        t3.start();

类似于这样 就会发现t1与t3线程进行抢占执行 而且线程不安全

由此可见当锁普通的方法时synchronized只能锁创建的类对象 当两个线程作用的类对象不相同 而需要进行线程安全设置时 锁也就失去了意义

  • synchronized锁普通类相当于synchronized(this)
  • 而这里的this相当于当前类对象myThread1
  • 当执行t1线程的时候上锁 t1线程执行完毕 下锁继续执行下一个线程 当下一个线程开始执行 上锁 执行完毕 下锁 以此类推

3.线程通信

1.等待

使用在对obj加锁的同步代码块中,在一个线程中,调用obj.wait()时,此线程会释放所拥有的所有锁标记。同时此线程阻塞在o的等待队列中。释放锁进入等待队列

//两种使用方法
public final void wait()   
public final void wait(long timeout)

2.通知

利用通知方法来唤醒等待线程

//两种唤醒方法
public final void notify()
public final void notifyAll()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值