基础学习day11--多线程一线程的创建,运行,同步和锁

1.1、进程和线程

进程:一个应用程序一般都是一个进程,正在进行的程序

每一个进程最少都有一个线程,都有一个执行顺序,该顺序是一个执行路径或者一个控制单元

线程:进程中一个独立的控制单元,线程控制着进程的执行。

windows中的任务管理器,可以查看进程,linux下通过ps命令

线程是进程的最小单位

线程依赖于进程

线程随着进程的创建和创建,随着进程的结束而消亡

如迅雷:可以同时开启多个下载,就是多线程

多个程序同时执行,时CPU在很快的切换,看上去是同时执行,实际上是在CPU在切换执行。

多线程存在的意义:可以让程序中的内容同时执行。

二、继承线程的创建

2.1、继承Thread,重写run方法

package com.pb.thread.demo1;

/**
 *
 * @author Denny
 * 继承Thread 类并重写run方法来创建线程类
 *
 */
public class MyThread extends Thread {

    private int count;

    /*
     * 重写run 方法
     * @see java.lang.Thread#run()
     */
    @Override
    public void run(){
        /*
         * 要运行的代码块或者方法,在这里调用,或者直接写在这里
         */
        while(count<10){
        count++;
        System.out.println("My thread run方法启动了"+count);
        }
    }
   public static void main(String[] args) {
       //声明线程类
       MyThread mt=new MyThread();
       //启动线程,JVM调用run方法
       mt.start();
       //主线程
       for(int x=0;x<10;x++){
          System.out.println("main thread"+x);
       }
}

}

多个线程都在抢占CPU的执行权,谁抢到,谁就执行

在某一时刻,只能有一个程序在运行

CPU在做着快速切换,以达到看上去是同时运行的效果。

多线程一个特性:随机性,谁抢到谁执行.

三、线程的运行和线程状态

3.1、调用start()方法

使该线程开始执行,Java虚拟机调用该线程的run()方法

为什么要重写run方法.

Thread类用于描述线程。

这个类定义一个功能,用于存储线程要运行的代码。该存储功能就是run方法.

也就是说,Thread类中的run方法是用于存储线程要运行的代码

如果直接调用run()方法,就是调用对象的普通方法一样.,仅仅是对象调用方法.线程创建了并没有运行。

只有start()才可以运行线程。

3.2、线程状态

新生:创建线程 new Thread()或者子类

运行:正在运行的线程,调用start()方法

冻结:已经创建的线程,但非运行状态的线程。sleep(long 毫秒), wait()线程等待,直到notify()唤醒才可以继续运行

临时状态阻塞:具备运行资格,但没有执行权,就是还没有被CPU切换到.

消亡:线程死亡stop(),或者线程运行完成。

四、获取线程对象

4.1、获取当前线程对象和名称

继承thread类实现线程,局部变量都有单独的一份不能共享数据

package com.pb.thread.demo1;

/**
 *
 * @author Denny
 * 继承Thread 类并重写run方法来创建线程类
 *Thread.currentThread(),获取当前线程对象
 *继承thread类实现线程,局部变量都有单独的一份不能共享数据
 */
public class MyThread extends Thread {

    public MyThread(String name){
        super(name);
    }
    /*
     * 重写run 方法
     * @see java.lang.Thread#run()
     */
    @Override
    public void run(){
        /*
         * 要运行的代码块或者方法,在这里调用,或者直接写在这里
         */
        for(int x=0;x<10;x++){

        System.out.println("My thread run的名字:"+Thread.currentThread().getName()+","+x);
        }
    }
   public static void main(String[] args) {
       //声明线程类
       MyThread mt1=new MyThread("mt1");
      // mt1.setName("张三"); 设置线程名称
       MyThread mt2=new MyThread("mt2");
       //启动线程,JVM调用run方法
       mt1.start();
       mt2.start();
       //主线程
       for(int x=0;x<10;x++){
          System.out.println(currentThread().getName()+","+x);
       }
}

}

示例:

五、接口实现线程

5.1、实现Runnable接口

重写run方法()

实现接口的方式最大的好处是可以共享数据

示例:多窗口同时售票,

package com.pb.thread.demo1;

/**
 *
 * @author Administrator 多个窗口同时卖票
 *
 */
public class Ticket implements Runnable {

    private  int tick = 100;

    public void run() {

        while (true) {
            if (tick > 0) {
                System.out.println(Thread.currentThread().getName()+"卖:" + tick--);
            }else{
                break;
            }
        }
    }
    public static void main(String[] args) {
        //声明线程类
        Ticket ticket=new Ticket();
        //创建线程对象,并将类做为参数
        Thread t1=new Thread(ticket);
        t1.setName("一号窗口,");
        Thread t2=new Thread(ticket);
        t2.setName("二号窗口,");
        Thread t3=new Thread(ticket);
        t3.setName("三号窗口,");
        Thread t4=new Thread(ticket);
        t4.setName("四号窗口,");
        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }

}

结果:

  1 一号窗口,卖:100
  2 一号窗口,卖:98
  3 一号窗口,卖:97
  4 一号窗口,卖:96
  5 一号窗口,卖:95
  6 一号窗口,卖:94
  7 二号窗口,卖:99
  8 二号窗口,卖:92
  9 一号窗口,卖:93
 10 一号窗口,卖:88
 11 一号窗口,卖:87
 12 一号窗口,卖:86
 13 二号窗口,卖:89
 14 二号窗口,卖:84
 15 二号窗口,卖:83
 16 二号窗口,卖:82
 17 二号窗口,卖:81
 18 二号窗口,卖:80
 19 二号窗口,卖:79
 20 二号窗口,卖:78
 21 二号窗口,卖:77
 22 二号窗口,卖:76
 23 二号窗口,卖:75
 24 二号窗口,卖:74
 25 二号窗口,卖:73
 26 二号窗口,卖:72
 27 二号窗口,卖:71
 28 二号窗口,卖:70
 29 二号窗口,卖:69
 30 二号窗口,卖:68
 31 二号窗口,卖:67
 32 二号窗口,卖:66
 33 二号窗口,卖:65
 34 二号窗口,卖:64
 35 二号窗口,卖:63
 36 二号窗口,卖:62
 37 二号窗口,卖:61
 38 二号窗口,卖:60
 39 二号窗口,卖:59
 40 二号窗口,卖:58
 41 二号窗口,卖:57
 42 二号窗口,卖:56
 43 二号窗口,卖:55
 44 二号窗口,卖:54
 45 二号窗口,卖:53
 46 二号窗口,卖:52
 47 二号窗口,卖:51
 48 二号窗口,卖:50
 49 二号窗口,卖:49
 50 二号窗口,卖:48
 51 二号窗口,卖:47
 52 二号窗口,卖:46
 53 二号窗口,卖:45
 54 二号窗口,卖:44
 55 二号窗口,卖:43
 56 二号窗口,卖:42
 57 二号窗口,卖:41
 58 二号窗口,卖:40
 59 二号窗口,卖:39
 60 二号窗口,卖:38
 61 二号窗口,卖:37
 62 二号窗口,卖:36
 63 二号窗口,卖:35
 64 二号窗口,卖:34
 65 二号窗口,卖:33
 66 二号窗口,卖:32
 67 二号窗口,卖:31
 68 二号窗口,卖:30
 69 二号窗口,卖:29
 70 二号窗口,卖:28
 71 二号窗口,卖:27
 72 二号窗口,卖:26
 73 二号窗口,卖:25
 74 二号窗口,卖:24
 75 二号窗口,卖:23
 76 二号窗口,卖:22
 77 二号窗口,卖:21
 78 三号窗口,卖:90
 79 四号窗口,卖:91
 80 三号窗口,卖:19
 81 二号窗口,卖:20
 82 一号窗口,卖:85
 83 二号窗口,卖:16
 84 三号窗口,卖:17
 85 四号窗口,卖:18
 86 三号窗口,卖:13
 87 三号窗口,卖:11
 88 三号窗口,卖:10
 89 三号窗口,卖:9
 90 三号窗口,卖:8
 91 三号窗口,卖:7
 92 三号窗口,卖:6
 93 三号窗口,卖:5
 94 三号窗口,卖:4
 95 三号窗口,卖:3
 96 三号窗口,卖:2
 97 三号窗口,卖:1
 98 二号窗口,卖:14
 99 一号窗口,卖:15
100 四号窗口,卖:12

两种创建线程方式:

  优点    缺点
继承Thread类
1.编写简单

2.可以使用this关键字直接访问当前线程


无法继承其它类

无法实现数据共享

实现Runnable接口
1.可以继承其它类

2.多个线程之间可以使用同一个Runnable对象

3.可以共享数据

编程方式稍微复杂,如需访问当前线程,需要调用Thread类的currentThread()方法                                                                                                              

                                   
                                 

六、线程安全

6.1、还是上面的例子

加上sleep(1000)睡觉1秒

package com.day10.thread.demo1;

public class Ticket implements Runnable {
    private int num=100;

    @Override
    public void run() {

        while(true){
            if(num>0){
                try {
                    Thread.sleep(1000);  //当前线程睡觉1秒,毫秒单位
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+",卖出"+num--+"号票");
            }
        }
    }
    public static void main(String[] args) {
        Ticket t=new Ticket();
        Thread t1=new Thread(t);
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);
        Thread t4=new Thread(t);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }

}

结果:

Picked up JAVA_TOOL_OPTIONS: -javaagent:/usr/share/java/jayatanaag.jar
Thread-0,卖出100号票
Thread-2,卖出99号票
Thread-1,卖出98号票
Thread-3,卖出97号票
Thread-0,卖出96号票
Thread-2,卖出95号票
Thread-1,卖出94号票
Thread-3,卖出93号票
Thread-0,卖出92号票
Thread-2,卖出91号票
Thread-1,卖出90号票
Thread-3,卖出89号票
Thread-0,卖出88号票
Thread-2,卖出87号票
Thread-1,卖出86号票
Thread-3,卖出85号票
Thread-0,卖出84号票
Thread-2,卖出83号票
Thread-1,卖出82号票
Thread-3,卖出81号票
Thread-0,卖出80号票
Thread-2,卖出79号票
Thread-1,卖出78号票
Thread-3,卖出77号票
Thread-0,卖出76号票
Thread-2,卖出75号票
Thread-1,卖出74号票
Thread-3,卖出73号票
Thread-0,卖出72号票
Thread-2,卖出71号票
Thread-1,卖出70号票
Thread-3,卖出69号票
Thread-0,卖出68号票
Thread-2,卖出67号票
Thread-1,卖出66号票
Thread-3,卖出65号票
Thread-0,卖出64号票
Thread-2,卖出63号票
Thread-1,卖出62号票
Thread-3,卖出61号票
Thread-0,卖出60号票
Thread-2,卖出59号票
Thread-1,卖出58号票
Thread-3,卖出57号票
Thread-0,卖出56号票
Thread-2,卖出55号票
Thread-1,卖出54号票
Thread-3,卖出53号票
Thread-0,卖出52号票
Thread-2,卖出51号票
Thread-1,卖出50号票
Thread-3,卖出49号票
Thread-0,卖出48号票
Thread-2,卖出47号票
Thread-1,卖出46号票
Thread-3,卖出45号票
Thread-0,卖出44号票
Thread-2,卖出43号票
Thread-1,卖出42号票
Thread-3,卖出41号票
Thread-0,卖出40号票
Thread-2,卖出39号票
Thread-1,卖出38号票
Thread-3,卖出37号票
Thread-0,卖出36号票
Thread-2,卖出35号票
Thread-1,卖出34号票
Thread-3,卖出33号票
Thread-0,卖出32号票
Thread-2,卖出31号票
Thread-1,卖出30号票
Thread-3,卖出29号票
Thread-0,卖出28号票
Thread-2,卖出27号票
Thread-1,卖出26号票
Thread-3,卖出25号票
Thread-0,卖出24号票
Thread-2,卖出23号票
Thread-1,卖出22号票
Thread-3,卖出21号票
Thread-0,卖出20号票
Thread-2,卖出19号票
Thread-1,卖出18号票
Thread-3,卖出17号票
Thread-0,卖出16号票
Thread-2,卖出15号票
Thread-1,卖出14号票
Thread-3,卖出13号票
Thread-0,卖出12号票
Thread-2,卖出11号票
Thread-1,卖出10号票
Thread-3,卖出9号票
Thread-0,卖出8号票
Thread-2,卖出7号票
Thread-1,卖出6号票
Thread-3,卖出5号票
Thread-0,卖出4号票
Thread-2,卖出3号票
Thread-1,卖出2号票
Thread-3,卖出1号票
Thread-0,卖出0号票
Thread-2,卖出-1号票
Thread-1,卖出-2号票

发现多卖票了,

为什么?因为卖票当前线程睡眠了1秒,其它线程就可以把这张票已经卖出了,

条件检查1>0,如果4个人同时检查,条件成立,就继续卖票就出现了,负数

怎么解决?给线程加锁

线程安全问题产生的原因:

1. 多个线程在操作共享的数据。
    2. 操作共享数据的线程代码有多条。
    当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。

解决方式:就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程不可以参与运算。必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。

看下面的同步synchronized

七、同步代码块

7.1、synchronized

同步代码块的格式:
    synchronized(对象){
           需要被同步的代码;
    } 
    同步的好处:解决了线程的安全问题。
    同步的弊端:当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。
    同步的前提:必须有多个线程并使用同一个锁。

修改上面的代码

package com.day10.thread.demo1;

public class Ticket implements Runnable {
    private int num=100;

    @Override
    public void run() {

        while(true){
            synchronized(this){
            if(num>0){
                try {
                    Thread.sleep(1000);  //当前线程睡觉1秒,毫秒单位
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+",卖出"+num--+"号票");
            }else{
                break;
            }
            }
        }
    }
    public static void main(String[] args) {
        Ticket t=new Ticket();
        Thread t1=new Thread(t);
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);
        Thread t4=new Thread(t);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }

}

八、同步函数

8.1、同步方法

package com.day10.thread.demo2;

public class Account {

    //余额
    private double blance=500;

    //取款
    public void withDraw(int num){

        blance=blance-num; 

    }

    public double getBlance() {
        return blance;
    }

    public void setBlance(double blance) {
        this.blance = blance;
    }

}
package com.day10.thread.demo2;

public class AccountThread implements Runnable {

    private Account account=new Account();
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            if(account.getBlance()<0){
                System.out.println("透支了!!");
            }
            makWithDraw(100); //每次取100
        }

    }

    /*
     * 取款的方法
     */
    public void makWithDraw(int num){
        //判断余额是不是大于要取款的数
        if(account.getBlance()>=num){
            System.out.println(Thread.currentThread().getName()+":准备取款!");
            try {
                Thread.sleep(1000); //等待1秒
                account.withDraw(num);
                System.out.println(Thread.currentThread().getName()+":取款完成!,当前余额为:"+account.getBlance());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }else{
            System.out.println(Thread.currentThread().getName()+"  余额不足以支付当前取款, 余额为:  "+account.getBlance());
        }
    }

}
package com.day10.thread.demo2;

public class Demo {

    public static void main(String[] args) {

        AccountThread at=new AccountThread();
        Thread t1=new Thread(at);
        t1.setName("张三");
        Thread t2=new Thread(at);
        t2.setName("张三老婆");
        t1.start();
        t2.start();
    }

}

结果:

张三:准备取款!
张三老婆:准备取款!
张三:取款完成!,当前余额为:400.0
张三:准备取款!
张三老婆:取款完成!,当前余额为:300.0
张三老婆:准备取款!
张三:取款完成!,当前余额为:200.0
张三:准备取款!
张三老婆:取款完成!,当前余额为:100.0
张三老婆:准备取款!
张三:取款完成!,当前余额为:0.0
张三  余额不足以支付当前取款, 余额为:  0.0
张三  余额不足以支付当前取款, 余额为:  0.0
张三老婆:取款完成!,当前余额为:-100.0
透支了!!
张三老婆  余额不足以支付当前取款, 余额为:  -100.0
透支了!!
张三老婆  余额不足以支付当前取款, 余额为:  -100.0

加上同步关键字

/*
     * 取款的方法
     */
    public  synchronized void makWithDraw(int num){
        //判断余额是不是大于要取款的数
        if(account.getBlance()>=num){
            System.out.println(Thread.currentThread().getName()+":准备取款!");
            try {
                Thread.sleep(1000); //等待1秒
                account.withDraw(num);
                System.out.println(Thread.currentThread().getName()+":取款完成!,当前余额为:"+account.getBlance());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }else{
            System.out.println(Thread.currentThread().getName()+"  余额不足以支付当前取款, 余额为:  "+account.getBlance());
        }
    }

结果:

张三:准备取款!
张三:取款完成!,当前余额为:400.0
张三老婆:准备取款!
张三老婆:取款完成!,当前余额为:300.0
张三:准备取款!
张三:取款完成!,当前余额为:200.0
张三:准备取款!
张三:取款完成!,当前余额为:100.0
张三:准备取款!
张三:取款完成!,当前余额为:0.0
张三  余额不足以支付当前取款, 余额为:  0.0
张三老婆  余额不足以支付当前取款, 余额为:  0.0
张三老婆  余额不足以支付当前取款, 余额为:  0.0
张三老婆  余额不足以支付当前取款, 余额为:  0.0
张三老婆  余额不足以支付当前取款, 余额为:  0.0

没有发生透支现象

同步代码块:

/*
     * 取款的方法
     */
    public   void makWithDraw(int num){
        synchronized(account){
        //判断余额是不是大于要取款的数
        if(account.getBlance()>=num){
            System.out.println(Thread.currentThread().getName()+":准备取款!");
            try {
                Thread.sleep(1000); //等待1秒
                account.withDraw(num);
                System.out.println(Thread.currentThread().getName()+":取款完成!,当前余额为:"+account.getBlance());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }else{
            System.out.println(Thread.currentThread().getName()+"  余额不足以支付当前取款, 余额为:  "+account.getBlance());
        }
        }
    }

结果同上,没有发生透支现象

同步函数和同步代码块的区别:
    1. 同步函数的锁是固定的this。
    2. 同步代码块的锁是任意的对象。
    建议使用同步代码块。

由于同步函数的锁是固定的this,同步代码块的锁是任意的对象,那么如果同步函数和同步代码块都使用this作为锁,就可以实现同步。

九、同步锁

9.1、同锁

同步方法同步对象是this,同步代码块也可以使用this来同步

十、静态同步

10.1、静态同步

不是this,因为静态方法中也不可以定义this

静态进内存,内存中没有本类对象,但是一定有该类对应的字节码文件对象

静态的同步函数使用的锁是该函数所属字节码文件对象,可以用getClass方法获取,也可以用当前类名.class表示。

synchronizid(类名.class){  或者对象.getClass

}

十一、单例模式加上同步懒汉式

11.1、懒汉式加锁

package com.day10.thread.demo2;
/**
 *
 * @author denny
 *单例模式
 *饿汉式,不存在复生成对象的问题
 *懒汉工,加synchronize
 */
public class SingleDemo {
    private static SingleDemo singleDemo;

    private SingleDemo(){

    }
    public static SingleDemo getNewIntance(){
        if(singleDemo==null){//判断是不是空,不是空就直接返回,是空就加锁
            synchronized(SingleDemo.class){  //加锁 //this.getClass() 直接写对象singleDemo.getClass()也行

            if(singleDemo==null){
                singleDemo=new SingleDemo();
            }
            }
        }
        return singleDemo;

    }

}

十二、死锁

12.1、死锁常见情景之一:同步的嵌套。

 class MyLock{
     static  Object lockA=new Object();
     static   Object lockB=new Object();
}

public class Demo implements Runnable {

    private boolean flag;

    public Demo(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {

            if (flag) {
                while (true) {
                synchronized (MyLock.lockA) {
                    System.out.println("if.........lockA");
                    synchronized (MyLock.lockB) {
                        System.out.println("if.........lockB");
                    }
                }
            }
            }
             else {
                 while(true){
                synchronized (MyLock.lockB) {
                    System.out.println("else.........lockB");
                    synchronized (MyLock.lockA) {
                        System.out.println("else.........lockA");
                    }
                }
                }

            }
        }

    public static void main(String[] args) {
        Thread t1 = new Thread(new Demo(true));
        Thread t2 = new Thread(new Demo(false));
        t1.start();
        t2.start();
    }

}

建议将要锁的对象,声明为static

时间: 2024-10-17 21:42:34

基础学习day11--多线程一线程的创建,运行,同步和锁的相关文章

[原]基础学习视频解码之视频线程

在上两篇文章[原]零基础学习视频解码之解码图像和[原]零基础学习视频解码之解码声音我们初步了解如何解码视频图像和视频声音.但是这些都是初步简单的解码出来而已,我们的主要功能是处理非常多:它是通过事件循环中运行,读取数据包,并在视频解码.所以,我们要做的就是拆分这些功能:我们将有一个线程,该线程将负责数据包进行解码;这些数据包将被添加到该队列中,并通过相应的音频和视频解码线程读取. 音频线:我们在上一篇已经建立了我们想要的方式; 视频线:视频线会相对比较麻烦一些,因为我们要自己显示自己的视频画面.

Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁

互斥锁通信机制 基本原理 互斥锁以排他方式防止共享数据被并发访问,互斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个互斥锁逻辑上绑定之后,对该资源的访问操作如下: (1)在访问该资源之前需要首先申请互斥锁,如果锁处于开状态,则申请得到锁并立即上锁(关),防止其他进程访问资源,如果锁处于关,则默认阻塞等待. (2)只有锁定该互斥锁的进程才能释放该互斥锁. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 互斥量

Java多线程之线程的创建

好久没有更博客了,最近一直在忙工作的事情.现在终于空下来了,这2天会抓紧时间整理多线程和socket,把JavaSE结束掉. 关于多线程,首先会涉及到哪些东西呢?首先要了解线程,为什么要使用线程,线程有什么优势,线程和进程有什么区别呢?了解过大致的线程内容后,就应该编码来实现Java的多线程了.首先2种方式来创建线程类,然后调用对应的API来控制线程.然后还剩下一个最大的也是最重要的一块知识,就是线程同步.前面那些了解线程的生命周期就可以,实际编码中并不会多次写到那些编码,但是线程的同步经常要用

Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)

线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public class Thread implements Runnable { /* What will be run. */ private Runnable target; ...... /** * Causes this thread to begin execution; the Java Virtu

java多线程学习(二)——线程的创建

一.java创建线程的两个方法 1.从java.lang.Thread类派生出一个新的线程类,重载它的run()方法 2.实现Runnable接口,重载Runnable接口中的run()方法. 使用Thread类来创建线程和创建普通类的对象的操作是一样的,线程是Thread类或者其子类的实例对象. 二.java提供的两种创建线程的区别 java中类是单继承的,当定义一个新的线程类的时候,它只能扩展一个外部类,那么当创建的线程是继承自Thread类来实现的,那么此线程类无法再扩展其他类,无法实现复

Java基础学习之-多线程学习知识点的学习

Java语言从设计之初就把多线程作为语言的核心, 至少从以下几点可以看出: 1. Object对象的wait和notify机制. 2. Thread类在lang包中. 3. synchronized volatile关键字. 虽然多线程是Java语言本身的特性,但是线程并不是Java语言独有的东西,而是操作系统的特性.Java在语言层面进行了封装,使其使用更简单. 多线程存在的价值在哪里呢? 内存读写,磁盘IO, 网络传输的速率远远低于CPU处理数据的速度.所以在大部分场景下,CPU是闲置的.有

JAVA基础学习之多线程

进程与线程 进程:就是正在进行的程序.其实就是一个应用程序运行时的内存空间. 线程:线程就是进程当中的一个控制单元或执行路径.进程负责空间的标示,而线程负责执行应用程序的执行顺序. 当一个进程中出现多个线程是就是多线程.每个线程在栈中都有自己的执行空间.方法区.变量. java VM启动的时候会有一个进程java.exe.该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中.该线程称之为主线程. 线程的创建方法 创建线程中第一种方式:继承Thread类. 步骤

java线程研究---(8)Thread同步:锁的概念

(多线程数据共用的)示例代码: 先来看看"java线程研究---(7)Thread同步:多线程数据共用会产生问题"这篇文章里面主要的代码例子 ShareDataThread.java package thread; public class ShareDataThread implements Runnable { private int i = 0; @Override public void run() { while (i < 10) { i++; for (int j =

第二十七节(多线程、线程的创建和启动、生命周期、调度、控制、同步)

线程指进程中的一个执行场景,也就是执行流程,那么进程和线程的区别是什么 1. 每个进程是一个应用程序,都有独立的内存空间 2. 同一个进程中的线程共享其进程中的内存和资源 (共享的内存是堆内存和方法区内存,栈内存不共享,每个线程有自己的) 什么是进程? 一个进程对应一个应用程序. 例如:在 windows 操作系统启动 Word 就表示启动了一个进程.在 java 的开发环境下启动 JVM, 就表示启动了一个进程.现代的计算机都是支持多进程的,在同一个操作系统中,可以同时启动多个进程. /* 分

Java并发学习之十——用线程工厂创建线程

本文是学习网络上的文章时的总结,感谢大家无私的分享. 1.工厂模式是最有用的设计模式.它是一个创造模式,还有他的目的是创建一个 或者几个类对象的对象.有了这个工厂,我们有这些优势集中创建对象: 更简单的改变了类的对象创建或者说创建这些对象的方式: 更简单的为了限制的资源限制了对象的创建. 更简单的生成创建对象的统计数据. 2.Java提供一个接口,ThreadFactory接口实现一个线程对象工厂 package chapter; import java.util.ArrayList; impo