java 线程

1并发与并行:并发:一个cpu交替执行多个任务,有时间差

  进程与线程   并行:多个cpu同时执行多个任务

                       进程:从rom进入到ram中运行的程序叫做进程

                       线程:打开程序,就会开启一条程序到cpu的路径,cpu可以通过该路径执行该程序

                                  的功能,这条路径就叫做线程。线程属于进程,是进程中的一个执行单元

                                  jvm在执行main方法时,main方法进入到栈内存,jvm会开辟一条main方法到

                                  cpu的执行路径,这个叫做主线程

2线程的调度:分为分时调度和抢占式调度,可以从任务管理器中设置

3创建多线程程序的第一种方法:创建thread类的子类

        创建的步骤:1创建thread类的子类,并重写其中的run方法,即,要这个线程具体做什么

                              2创建自定义thread类的对象

                              3调用thread类中的start方法每次调用start方法就是开辟一个新的栈空间。

                                thread.run和thread.start的区别就是每次调用start方法就是开辟一个新的

                                栈空间后再执行run方法。而run方法只是在main方法执行后再执行。

                                不会再新建栈空间。

案例1

//对thread类进行重写,创建我们需要的run方法
package com.bed.thread;

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

package com.bed.thread;
================================================
public class Mainthread {
    public static void main(String[] args) {
        //多线程方法
        MyThread mt=new MyThread();//新建Mythread类对象
        mt.start();//开启新的线程,调用其中我们已经重写了的run方法

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

         运行结果:两个线程随机运行,且发现每次结果不一样,main线程和新的线程一起抢夺CPU的执行权,谁抢到了就执行相应的代码。

                                                              

        注意:

4线程的几种方法:

        1获取当前线程的名称

      

重写run方法
package com.bed.thread;

public class ThreadGetName extends Thread{
    @Override
    public void run(){
        String name=getName();//直接使用getname方法来获取该线程的名称。
        System.out.println(name);

        Thread t=Thread.currentThread();//获取当前线程
        String name1 = t.getName();//获取当前线程名称
    }
}

package com.bed.thread;

public class GetName {
    public static void main(String[] args) {
        ThreadGetName tgn=new ThreadGetName();
        tgn.start();

        System.out.println(Thread.currentThread().getName());//写在主方法下面来获取主线程                                            名称
    }
}

         2 更改线程名称的两种方法:1Thread.setName 

                                                       2 创建带参数构造方法,方法参数是线程名称,

                                                          并把名称教给线程的父类suname)

         3Sleep方法:使当前执行线程按照给定毫秒暂停后继续运行

案例  60秒倒计时
public class Sleep {
    public static void main(String[] args) {
        for (int i = 0; i < 60; i++) {
            System.out.println(i);
            try {
                Thread.sleep(1000);//一千毫秒间隔
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

5创建多线程的第二种方法:使用runable实现类

                步骤:     

重写runable实现类中的run方法
public class Runable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"--"+i);
        }
    }
}

public class RunableMain {
    public static void main(String[] args) {
        Runnable r=new Runable();
        Thread th=new Thread(r);
        th.start();
        //主方法进程
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"--"+i);
        }
    }
}

        使用runable接口的便利性:

        

 6使用匿名内部类来创建多线程的方法:

                     

实例

package com.bed.thread;

public class InnerClassThread {
    public static void main(String[] args) {

        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName());
                }
            }
        }.start();
        //下面的代码就等于 Runable r=new RunableImpl();+new Thread(r).start;
        new Thread(new Runable(){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName());
                }
            }
        }).start();
    }
}

 7线程的安全问题:多个线程在抢夺同个资源的时候会出现的问题

        如何避免线程的安全问题:当一个线程在使用共享资源时,无论是否占用CPU。其他线程

        都只能等待其完成后再使用CPU。

8如何解决线程安全问题:

        1使用Synchronized关键字

                              

        通俗的讲,多个线程,只有抢到了这个“锁对象(obj)”,才能执行同步的代码块,

        执行完同步代码块就会把锁对象归还,其他线程才可以获取锁所对象,进行后面的

        同步代码块运行。但是频繁的获取锁,释放锁会降低程序的效率。

 案例

package com.bed.thread;

public class SoldTicket implements Runnable {
    private int ticket=100;//一共有一百张票
    Object obj=new Object();//创建一个锁对象

    @Override
    public void run() {
        while(true){
            synchronized (obj) {//需要锁住的代码部分
                if (ticket > 0) {//先判断还有没有票
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖出第" + ticket + "张票");
                    ticket--;
                }
            }
        }
    }
}

         2使用synchronized方法(和使用synchronized关键字一样,就是将共享同步代码装到一个

                方法里,然后调用方法即可)

                        

      3使用lock锁:

           1在成员方法处创建一个lock的实现类对象Lock L1=new Reentrantlock();

           2在共享代码前调用lock方法  L1.lock{可能会出安全问题的代码前创建锁}

           3在可能出问题的代码后添加L.unlock();释放锁

代码实现

package com.bed.thread;

import java.util.concurrent.locks.ReentrantLock;

public class Locktest implements Runnable {
        private int ticket=100;//一共有一百张票
        ReentrantLock L1=new ReentrantLock();

        @Override
public void run() {
            while(true){
                L1.lock();//获取锁
                    if (ticket > 0) {//先判断还有没有票
                        try {
                            Thread.sleep(10);
                            System.out.println(Thread.currentThread().getName() + "卖出第"                         + ticket + "张票");
                            ticket--;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }finally {
                            L1.unlock();//释放锁,无论程序是否有问题锁都会释放掉
                        }
                    }
                }
            }
}

 9线程执行的6种状态: 

 10代码实现 等待-唤醒 案例(线程之间的通信)

//实现一个购买的构成,消费者先告知生产者需要什么,然后进行等待。生产者经过一段时间后。
    //将生产好的产品交给消费者。
//购买者:告知购买意向,然后调用wait方法进入等待,等待生产者生产。
//生产者:花费五秒钟来制作,做好之后调用notify再告知购买者。
public class WaitCall {
    public static void main(String[] args) {
        Object obj = new Object();//新建一个锁对象

        new Thread() {//消费者模拟
            @Override
            public void run() {
                synchronized (obj){//同步锁保证等待线程与唤醒线程只能有一个运行
                    System.out.println("我需要买这个那个");
                    try {
                        obj.wait();//告知需求后进入睡眠状态
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("谢谢");//在wait结束后进行的代码
                }
            }
        }.start();//启动该线程

        new Thread(){//生产者模拟

            @Override
            public void run() {
                synchronized (obj){//此处的锁要与上面的一样
                    try {//制作时长为五秒
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("制作完毕,您拿好");
                    obj.notify();//唤醒第一线程
                }
            }
        }.start();
    }
}

 补充:

        唤醒时除了notify方法  还有一个notifyall方法,就是唤醒所有等待线程的意思

11线程间的通信

  等待与唤醒机制(线程间的通信):解决多个线程抢夺同一个资源的问题。

  案例:买卖包子

待理解

12线程池:就是多个线程的容器,可以用linkedlist进行集合。用Thread t=linked.remove来调用。

              调用完后,用linked.add(t)来添加。使用线程池可以提高程序的效率。

    使用线程池:

package com.bed;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class threadpool {
    public static void main(String[] args) {
        //创建一个线程数量为3的线程池
        ExecutorService es = Executors.newFixedThreadPool(3);
        //将写完的线程开启
        es.submit(new runable());
        es.submit(new runable());
        es.submit(new runable());
    }
}

 

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值