【Java基础总结】多线程

1. java中实现多线程的两种方式

 1 //第一种:继承Thread类,重写run()方法
 2 class ThreadTest1 extends Thread{
 3     public void run(){
 4         String threadName = Thread.currentThread().getName();
 5         for(int i=0;i<10;i++){
 6             System.out.println("ThreadTest1 "+threadName+" running ... "+i);
 7         }
 8     }
 9 }
10
11 //第二种:实现Runnable接口,重写run()方法
12 class ThreadTest2 implements Runnable{
13     public void run(){
14         String threadName = Thread.currentThread().getName();
15         for(int i=0;i<10;i++){
16             System.out.println("ThreadTest2 "+threadName+" running ... "+i);
17         }
18     }
19 }
20
21 public class Thread01{
22     public static void main(String[] args){
23         ThreadTest1 t1 = new ThreadTest1();
24         ThreadTest1 t2 = new ThreadTest1();
25         Thread t3 = new Thread(new ThreadTest2());  //注意
26         Thread t4 = new Thread(new ThreadTest2());
27
28         //start() 启动线程
29         t1.start();
30         t2.start();
31         t3.start();
32         t4.start();
33     }
34 }

归根结底,两种方法都是用Thread类或其子类对象调用start()方法启动线程。

为什么用start()方法而不用run()方法启动线程呢?因为start()方法产生了运行这个线程所需的系统资源,安排其运行,并调用线程体(run()方法)。

一个线程只能启动一次,不管调用多少次start()方法,结果也只用一个线程。

2. 线程共享资源

建议实现Runnable接口,其好处是:

  • 多线程之间可以共享资源
  • 避免单继承带来的问题
  • 数据和代码独立
 1 class ThreadTest2 implements Runnable{
 2     private int count=20;    //共享资源
 3     public void run(){
 4         String threadName = Thread.currentThread().getName();
 5         while(count>0){
 6             System.out.println("ThreadTest2 "+threadName+" 售出 "+count+" 号票");
 7             count--;
 8         }
 9     }
10 }
11
12 public class ThreadDemo2{
13     public static void main(String[] args){
14         ThreadTest2 t2 = new ThreadTest2();
15         (new Thread(t2,"窗口1")).start();
16         (new Thread(t2,"窗口2")).start();
17         (new Thread(t2,"窗口3")).start();
18         (new Thread(t2,"窗口4")).start();
19     }
20 }

运行结果:

ThreadTest2 窗口1 售出 20 号票
ThreadTest2 窗口1 售出 19 号票
ThreadTest2 窗口3 售出 20 号票
ThreadTest2 窗口2 售出 20 号票
ThreadTest2 窗口3 售出 17 号票
ThreadTest2 窗口1 售出 18 号票
ThreadTest2 窗口1 售出 14 号票
ThreadTest2 窗口4 售出 19 号票
ThreadTest2 窗口1 售出 13 号票
ThreadTest2 窗口3 售出 15 号票
ThreadTest2 窗口3 售出 10 号票
ThreadTest2 窗口2 售出 16 号票
ThreadTest2 窗口2 售出 8 号票
ThreadTest2 窗口3 售出 9 号票
ThreadTest2 窗口1 售出 11 号票
ThreadTest2 窗口4 售出 12 号票
ThreadTest2 窗口1 售出 5 号票
ThreadTest2 窗口3 售出 6 号票
ThreadTest2 窗口2 售出 7 号票
ThreadTest2 窗口3 售出 2 号票
ThreadTest2 窗口1 售出 3 号票
ThreadTest2 窗口4 售出 4 号票
ThreadTest2 窗口2 售出 1 号票

问题:多个窗口售出了相同编号的票,发生了访问冲突。

3. 线程同步

同步synchronized意:协同步调,按照先后顺序进行;同步代码块;同步函数

前提:2个或2个以上的线程;使用同一把锁
作用:保证同步中只有一个线程在运行。
好处:解决线程安全问题
弊端:多个线程需要判断锁,消耗资源

在Java里面,同步锁的概念就是这样的。任何一个Object Reference都可以作为同步锁。我们可以把Object Reference理解为对象在内存分配系统中的内存地址。

解决方案:
1)同步代码块
    synchronized(类或对象)
    {
        需要同步的代码段
    }
2)同步函数
    (非static的情况)
    public synchronized void fun()
    {
        代码段
    }
    等价于
    public void fun()
    {
        synchronized(this)
        {
            代码段
        }
    }
    调用此同步函数的对象作为此同步函数的同步锁。

    (static的情况)
    public static synchronized void fun()
    {
        代码段
    }
    静态变量或静态方法加载到内存中时,内存中没有本类对象,但一定有了该类对应的
    字节码文件(类名.class),该对象的类型是class。静态同步函数使用的同步锁是所在类
    的字节码文件。        
 1 class ThreadTest implements Runnable
 2 {
 3     private int ticket=50;
 4     public void run(){
 5         while(ticket>0){
 6             String threadName = Thread.currentThread().getName();
 7             //同步代码块(越小越好)
 8             synchronized(this){
 9                 if(ticket>0){
10                     System.out.println(threadName + " sales ticket "+ticket);
11                     ticket--;
12                 }
13             }
14         }
15     }
16 }
17
18 public class Thread03{
19     public static void main(String[] args){
20         ThreadTest t = new ThreadTest();
21         (new Thread(t, "窗口A")).start();
22         (new Thread(t, "窗口B")).start();
23         (new Thread(t, "窗口C")).start();
24         (new Thread(t, "窗口D")).start();
25     }
26 }

运行结果:

窗口A sales ticket 50
窗口D sales ticket 49
窗口D sales ticket 48
窗口D sales ticket 47
窗口D sales ticket 46
窗口D sales ticket 45
窗口D sales ticket 44
窗口D sales ticket 43
窗口D sales ticket 42
窗口D sales ticket 41
窗口D sales ticket 40
窗口D sales ticket 39
窗口D sales ticket 38
窗口D sales ticket 37
窗口D sales ticket 36
窗口D sales ticket 35
窗口D sales ticket 34
窗口D sales ticket 33
窗口D sales ticket 32
窗口D sales ticket 31
窗口D sales ticket 30
窗口D sales ticket 29
窗口D sales ticket 28
窗口D sales ticket 27
窗口D sales ticket 26
窗口D sales ticket 25
窗口D sales ticket 24
窗口D sales ticket 23
窗口D sales ticket 22
窗口D sales ticket 21
窗口D sales ticket 20
窗口D sales ticket 19
窗口D sales ticket 18
窗口D sales ticket 17
窗口D sales ticket 16
窗口D sales ticket 15
窗口D sales ticket 14
窗口D sales ticket 13
窗口D sales ticket 12
窗口D sales ticket 11
窗口D sales ticket 10
窗口D sales ticket 9
窗口D sales ticket 8
窗口D sales ticket 7
窗口D sales ticket 6
窗口D sales ticket 5
窗口D sales ticket 4
窗口D sales ticket 3
窗口D sales ticket 2
窗口D sales ticket 1

4. 线程死锁

死锁现象即相互等待的局面
(操作系统中的死锁) 指2个或多个进程在执行过程,因竞争资源而造成一种互相等待的局面,若无外力干涉,进程无法推进下去。
发生死锁的原因一般是两个对象的锁相互等待造成的。
那么为什么会产生死锁呢?

  1. 因为系统资源不足。
  2. 进程运行推进的顺序不合适。
  3. 资源分配不当。

产生死锁的条件有四个:

  1. 互斥条件:所谓互斥就是进程在某一时间内独占资源。
  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

5. 单例模式

  特点:1.私有构造函数 2.在类中创建一个指向自己实例的私有静态引用 3.以自己实例为返回类型值的静态公有方法。

//饿汉式
class Singleton{
    private static final Singleton singleInstance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return singleInstance;
    }
}
//懒汉式
class Singleton{
    private static Singleton singleInstance =null;
    private Singleton(){}
    public static synchronized Singleton getInstance(){
        if(singleInstance==null){
            singleInstance = new Singleton();
        }
        return singleInstance;
    }
}

6. 线程通信(wait()和notify()、notifyAll())

  线程的状态

  

7. ReentrantLock和Condition

8. 停止线程的方法(interrupt()和isInterrupt())

9. 守护线程和join方法

  守护线程是为其他线程提供便利服务的,当全部的用户线程结束后,守护线程才会随JVM结束工作。 thread.setDaemon(true);

public static void main(String[] args){
    Thread t3 = new Thread(test2, "线程t3");
    t3.start();
    t3.join();
    //主线程就此陷入等待,直到t3线程结束。
}

10. 线程优先级和yield方法

线程的优先级从低到高:1-10,优先级高的的优先执行,每个新线程都继承了父线程的优先级,常量:Thread.MIN_PRIORITY 值为1,Thread.MAX_PRIORITY 值为10,Thread.NORM_PRIORITY 值为5

void setPriority(priority)
int getPriority()

  yield()方法将线程从执行状态变成就绪状态。

时间: 2024-10-13 16:18:34

【Java基础总结】多线程的相关文章

【BigData】Java基础_多线程

所谓的多线程就像小吃街卖铜锅米线的老板,老板就好比一个操作系统,如果5个顾客同时去买米线,那么,此时老板就会同时准备好5个铜锅,然后同时放上水.调料.米线,同时煮5个人的米线,如果逐个煮的话,那么估计煮了2个人的米线,后面3人就来找老板退款了. 官方解释:多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术 在Java中实现多线程四部曲: (1)将需要用多线程方式执行的逻辑,写入一个runnable实现类中(run方法中): (2)创建出这个runnabl

Java基础4——多线程

线程依赖于进程而存在 进程:正在运行的程序 是操作系统进行资源分配和调度的独立单位 每个进程都有自己的内存空间和系统资源 多进程的意义:单进程的计算机只能做一件事情 DOS窗口就是典型的单进程 多进程的计算机可以在一个时间段内执行多个任务 单核CPU在某个时间点只能执行一件事情,事实上CPU一直在高效切换各个进程 线程:一个进程内可以执行多个任务,每个任务可以看成是一个线程,线程是程序(进程)的执行单元或执行路径,是程序使用CPU的最小单位 多线程的意义:提高应用程序的使用率 程序的执行都是在抢

3.8 java基础总结①多线程

多线程 多线程这章理论大于实践,因为在实际开发中多线程的都封装到框架里边了的,程序员一般不会写多线程,多线程属于Java里边比较底层的代码了. 线程是处理器调度的最基本单位程序>进程>线程程序是死的,当启动程序得时候会有一个或几个进程,每个进程里边可以有诺干线程.基于线程开销更 创建线程:两种方法1.声明Thread的子类,重写run方法class MyThread extends Thread{ public void run(){ }}Mythread a = new MyThread()

Java基础知识—多线程编程(五)

概述 Java 给多线程编程提供了内置的支持.一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径.使用多线程也是为了充分的利用服务器资源,提高工作效率. 线程生命周期 线程是一个动态执行的过程,它也有一个从产生到死亡的过程. 新建状态: 使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态.它保持这个状态直到程序 start() 这个线程. 就绪状态: 当线程对象调用了start()方法之后,该

java基础之多线程

参考博客 http://www.mamicode.com/info-detail-517008.html 1.进程和线程的区别 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程. 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小. 线程和进程一样分为五个阶段:创建.就绪.运行.阻塞.终止. 多进程是指操作系统能同时运行多个任务(程序). 多线程是指在同一程序中有多个顺序流在执行. 2.实现R

java基础及多线程

1.多线程 1.1.进程与线程 ? 进程就是一个运行中的程序. ? 一个进程中可以有多个线程,线程是CPU调度和分派的基本单位.我们可以理解为线程就是程序运行中的一条路径. 1.2.多线程的创建及使用 1.2.1.创建 自定义一个类继承Thread类或实现Runnable接口 1.2.2:两种创建多线程的区别 继承Thread类:Thread()或Thread(String name) 多个线程分别完成自己的任务 实现Runnable接口:Thread(Runnable target) 或Thr

java基础07 多线程

在学习操作系统时,我们会学习进程和线程,那么进程和线程又是什么东西呢? 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程(thread)是操作系统能够进行运算调度的最小单位. 它被包含在进程之中,是进程中的实际运作单位. 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. Java程序运行原理 java 命令会启动 java 虚拟机,启动 JVM,等于启动了一个应用程序,也就是启动了一

黑马程序员-Java基础之多线程

多线程 进程:正在进行中的程序.其实进程就是一个应用程序运行时的内存分配空间. 线程:其实就是进程中一个程序执行控制单元,一条执行路径.进程负责的是应用程序的空间的标示.线程负责的是应用程序的执行顺序. 一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序,每个线程在栈区中都有自己的执行空间,自己的方法区.自己的变量. jvm在启动的时,首先有一个主线程,负责程序的执行,调用的是main函数.主线程执行的代码都在main方法中. 当产生垃圾时,收垃圾的动作,

Java基础总结--多线程总结2

----多线程通信-----1.概述:多个线程处理同一个资源,但是各自的任务不相同eg:线程1负责存储数据,线程2负责处理该数据.数据--就是同一个资源怎样用java语言描述上面的例子:* 资源是变化的--数据是变化的--将其封装为对象* 存在两个任务不同的线程,需要2个run方法--所以封装在两个不同的线程类中* 必须保证输入和输出处理的是同一个对象-输入输出构造方法传参数(参数为资源对象引用)* 主函数里面,创建资源对象,线程类对象,启动线程2.多线程通信依然会出现线程安全的问题解决办法--

【黑马程序员】-Java基础学习-多线程

------- android培训.java培训.期待与您交流! --------- 首先讲一下进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程. 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小. 线程和进程一样分为五个阶段:创建.就绪.运行.阻塞.终止. 多进程是指操作系统能同时运行多个任务(程序). 多线程是指在同一程序中有多个顺序流在执行.