欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java——线程学习笔记

程序员文章站 2022-06-21 10:53:46
...

1、线程的理解:

(1)线程的使用:

线程的学习难点并不在于如何创建、开启一个线程,而是应该何时创建,线程如何同步,使得程序能够运行得到预期的结果。
比如文字处理程序 你可以设置每隔多长时间 输入的内容可以自动的保存 而这个保存操作并不需要你的介入 而是使用一个线程专门负责这个操作,在这个程序中至少得有两个线程 一个便是主线程 用来捕获你从键盘输入的内容 而另一个线程则负责定时保存输入的内容。
在后面的socket的学习中也用到了多线程:

(2)线程的执行:

只有在多处理器的机器上, 多线程才会被真正的同时运行,在单处理机上多线程是占用分配的时间片来运行,因为处理机的速度比较快 使得我们看起来它像是在同时运行,也就是我们操作系统中所说的并发和并行的概念。

2、线程的创建:

方法一:定义线程实现Runnable接口
方法二:定义一个Thread的子类并重写run方法

代码实现

public class MyThread implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(int i=0;i<10;i++) {
            System.out.println("myThread"+i);
        }
    }
}

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

public class MainTread {
    public static void main(String[] args) {
            Runnable r1=new MyThread();
            //r1.run();这样只是执行了线程体,而不是开辟出类一个线程与主线程同时运行

            //这样就开辟出来一个新的线程 Thread(Runnable target)
            Thread t=new Thread(r1);//要启动一个新的线程就必须new一个Thread对象出来
            t.start();//线程启动调用start方法 线程执行默认运行的run()方法  

            /*
                方法二:
                MyThread1 mt=new MyThread1();
                mt.start();
            */
            for(int i=0;i<10;i++){
                System.out.println("mainthod:"+i);
            }

    }
}

3、线程的管理

(1)join()
    等待该线程终止,在当前线程中调用另一个线程的jion方法,则当前线程转入阻塞状态,直到另一个线程运行结束后,当前线程才会由阻塞状态转为就绪状态
代码实现:
    public class MainThread {
    public static void main(String[] args) {
        MyThread mt=new MyThread();
        MyThread1 mt1=new MyThread1();
        /*
         * Thread(Runnable target)分配新的target对象
         * */
        Thread tr1=new Thread(mt1);
        Thread tr=new Thread(mt);
        tr1.start();
        tr.start();

        try {
            tr1.join();
            tr.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        for(int i=0;i<50;i++) {
            System.out.println("MainThread"+i);
        }

        //tr1与tr线程若放在后面启动的话  则是等主线程结束后才会启动执行
        /*
         * 那么此处我们就开始思考了  线程的并发执行是无序的   我们该如何使得线程能够按照某种顺序执行呢?
         * 即采用jion方法了
         * */
        //tr1.start();
        //tr.start();

    }
此处代码运行的结果是 待tr tr1线程运行结束后 主线程才会开始运行
(2)yield和sleep

yield和sleep(0)实现的效果一样,因此我们可以发现它俩的区别是sleep可以规定该线程多长时间内不可以抢占处理机,而yield()不可以,它意味着该线程放弃处理机后立马可以参加抢占处理机
代码实现:

public class MyThread implements Runnable {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(int i=0;i<50;i++) {
            /*
             * 每循环一次 该线程让出了处理机   即处理机重新选择分配给一个线程 进行运行  仍有可能分配给原来的线程
             * */
            Thread.yield();
            System.out.println("MyThread"+i);
        }
    }

}

public class MyThread implements Runnable {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);//该线程休眠 5秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for(int i=0;i<50;i++) {

            System.out.println("MyThread"+i);
        }
    }

}
(3)设置线程的优先级
需要注意的是Java中
 优先级高的线程只能有机会优先被执行  而不会绝对被优先执行
代码实现:
public class MainThread {
    /*
     * 线程优先级设置测试
     * */
    public static void main(String[] args) {
        MyThread1 mt1=new MyThread1();
        MyThread2 mt2=new MyThread2();

        Thread tr1=new Thread(mt1);
        Thread tr2=new Thread(mt2);
        int p1 = tr1.getPriority();
        int p2 = tr2.getPriority();

        System.out.println(p1+"   "+p2);//线程的默认优先级为5

        //设置线程的优先级
        tr1.setPriority(10);
        tr2.setPriority(7);
        tr1.start();

        tr2.start();

        for(int i=0;i<50;i++) {
            System.out.println("MainThread  "+i);
        }   
    }
}
(4)wait(),notify()与 synchronized

需要先明白以下几个问题:
1、如何使用?
(1)obj.wait()(等待) 与 obj.notify()(唤醒) 必须要与synchronized(obj)方法一起使用
(2)wait()必须在synchronized代码块中,它使得当前线程等待,直到其它线程调用此对象的notify()或notifyAll()方法,即其它线程唤醒自己。
(3)notify()方法可不可以自己唤醒自己? 答案当然是NO,notify()唤醒的是在等待队列中的线程,自己就没有在等待队列,需要注意的是notify()唤醒的是等待队列中的随机一个线程, notifyAll()可将等待队列中的所有的线程全部唤醒
2、wait()与sleep的区别 。
sleep是线程的方法 wait是object的方法 sleep释放的CPU的抢占权 wait()将CPU的抢占权跟锁全部都释放

3、为什么要使用 synchronized?
多线程操作同一个对象的时候要加锁,不加锁的话会导致程序的执行无可再现性,每次的运行结果都不相同。
说了这么一大堆,比较抽象,使用线程模拟生产者消费者问题会加深理解 。
线程模拟生产者消费者问题

相关标签: 线程 Thread