`
new_Line
  • 浏览: 10264 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类
最新评论

黑马程序员_java多线程

 
阅读更多

------- android培训java培训、期待与您交流! ----------

进程:
    是一个正在运行中的程序,每一个进程执行,都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元
线程:
    进程中的一个独立的控制单元,线程在控制着进程的执行,一个进程中至少有一个线程(控制单元)
JVM:   
    运行时会有一个进程叫做java.exe,该进程中至少一个线程负责java程序的执行,而且这个程序的代码存在于main方法中该线程称之为主线程。
        扩展:其实更细节的说明JVM,JVM启动时不止一个线程,还有一个垃圾回收机制的线程
如何在自定义的代码中自定义一个线程呢?
    通过API文档,java已经提供了对线程这类事物的描述,就是Thread类。
继承Thread类(用于描述线程)
    步骤:
        1、首先,定义类继承Thread;
        2、复写Thread类中的run方法;目的:将自定义代码存储在run方法中,让线程执行
        3、调用线程的start方法(该方法有两个作用:启动线程和调用run()方法)
    示例:
        public class Test1 {
            public static void main(String[] args)
            {
                Demo d = new Demo();  //创建线程
                d.start();  //开启线程并执行该线程中的run方法
                //d.run();  //为什么不是调用该方法,因为调用该方法,虽然线程是创建了
                //但是并没有开启线程,所以还是单线程,按顺序执行代码
                for(int i = 0; i < 40; i++)
                    System.out.println("主线程的:-----" + i);
            }
        }
        class Demo extends Thread
        {
            public void run()
            {
                for(int i = 0; i < 40; i++)
                    System.out.println("子类的:----" + i);
            }
        }
    为什么要复写run方法呢?
        因为thread类定义了一个用于存储线程要运行的代码的方法,该方法就是run。
            也就是说Thread类中的run方法,用于存储线程要运行的代码,主线程中的代码存储于main方法中
    线程中的方法:
        Thread.currentThread()---->获取当前线程的名称
         getName()---->获取线程的名称
         setName()或者super(name)---->设置线程的名称
实现Runnable接口。
    步骤:
        1、定义类实现Runnable接口
        2、复写接口中的run方法
        3、创建实现Runnable接口对象
        4、创建Thread类对象,将实现Runnable接口的对象作为实际参数传递给Thread类的构造函数
        5、调用Thread类的start方法,开启接口
    示例:
        class MyRunnable implements Runnable
        {
            public void run()
            {
                for(int i = 0; i < 10; i++)
                {
                    System.out.println(Thread.currentThread() + "---->" + i);
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        public class Demo {
            public static void main(String[] args) throws InterruptedException
            {
                MyRunnable mb = new MyRunnable();
                Thread t = new Thread(mb);
                t.start();
                for(int i = 0; i < 22; i++)
                {
                    System.out.println(Thread.currentThread() + "---->" + i);
                    Thread.sleep(200);
                }
            }
        }
继承Thread类和实现Runnable接口有什么区别?
  继承Thread类:线程代码存放在Thread子类的run方法中
  实现Runnable:线程代码存放在Runnable实现类的run方法中
  实现Runnable避免了单继承的局限性,在定义线程时建议使用实现方式来完成
线程的生命周期:
    线程的生命周期包含状态:新状态、就绪状态、阻塞状态、死亡状态
    新状态:
        Thread t = new Thread();
        刚刚new出来的线程对象,还没有调用start()方法。
    就绪状态(可运行状态):
        t.start()之后,线程进入就绪状态!在某一个时间点上,只有一个线程是运行着的,其它的线程都没有运行,
        所以我们说start()之后不是“运行状态”,而是“就绪状态”。
        线程什么时候从就绪到运行,这由CPU来决定,?CPU会给运行的线程一个时间片,这个时间用完,
        如果线程还没有主动阻塞,那么CPU会强行停止运行,给其他线程运行机会。
    运行状态:
        由CPU决定,CPU会在就绪状态的线程中随机选择一个,给其运行的时间片。
        运行的线程,应该主动进入阻塞状态,这样给其他线程运行的时间。
    阻塞状态:
        睡眠:Thread.sleep(1000),当线程执行了sleep()方法,那么这个线程就进入了休眠状态。
              休眠的线程必须要等到指定的毫秒过完,才能返回到就绪状态。
        等待:当前线程执行了wait()方法,进入了对象的等待列表中。
              只能期待其他线程调用notify()或notifyAll()来唤醒这个等待的线程。
        IO阻塞:当线程正在完成IO操作,那么这个线程也就阻塞了。直到IO操作完成了!
        锁定: 当线程要使用的对象被其他线程使用时,那么这个线程进入了锁定状态。
               直到线程得到了要使用的对象后,那么就回到就绪状态。
    死亡状态:
        run()方法结束,正常死亡!
        run()中抛出了异常,因为而死亡!
线程中的常用方法:
    static Thread currentThread():获取当前线程的对象,相当于this
    String getName():获取当前线程的名称
    设置线程名称:void setName(String name)或通过构造器
当多个线程共享同一个数据时,导致共享数据出现错误。
解决方案:一个线程执行中,其它线程不能参与执行
Java对于多线程的安全问题,提供了专业的解决方案:
    同步代码块:
        synchronized(监视器对象)
        {
            //需要被同步的代码
        }
        虽然Java允许使用任何对象作为监视器对象,但想一下同步的目的:阻止多个线程对同一个共享资源并发访问,
        因此通常使用可能被并发访问的资源作为同步监视器对象。
        案例体现:模拟银行取钱操作
           
            package com.itheima.bank;
            public class Account {
                //账户余额
                private double balance;
                public Account(double balance) {
                    this.balance = balance;
                }
                /*取钱的方法*/
                public double drawBalance(double drawBalance)
                {
                    balance = balance - drawBalance;
                    return balance;
                }
                /*查询余额*/
                public double getBalance()
                {
                    return balance;
                }
            }

            package com.itheima.bank;
            public class DrawThread extends Thread
            {
                private Account a;
                //要取的金额
                private double drawBalance;
                public DrawThread(String name, Account a, double drawBalance)
                {
                    super(name);
                    this.a = a;
                    this.drawBalance = drawBalance;
                }
                public void run()
                {
                    while(true){
                        /*同步代码块,将共享访问的Account对象作为锁*/
                        synchronized(a){
                            if(a.getBalance() < drawBalance){
                                System.out.println(Thread.currentThread() + " : 余额不足,当前余额: " + a.getBalance());
                                break;
                            }
                            try {
                                Thread.sleep(10);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            a.drawBalance(drawBalance);
                            System.out.println(Thread.currentThread() + "取钱成功,取走金额:" + drawBalance + " ,当前余额:" + a.getBalance());
                        }
                    }
                }
            }

            package com.itheima.bank;
            public class DrawTest {
                public static void main(String[] args) {
                    Account a = new Account(1000);
                    new DrawThread("A账户:", a, 500).start();
                    new DrawThread("B账户:", a, 300).start();
                }
            }
    同步方法:
        同步方法是使用synchronized关键字来修饰某个方法,则该方法就被称为同步方法。
            例如:public synchronized void show(){}
        对于同步方法而言,无需显示指定同步监视器对象,同步方法的同步监视器对象是this。
        同步方法的特点:一个对象的一个同步方法被调用,它的其它同步方法都用不了
        案例体现:
            package com.itheima;
            public class SynDemo1 {
                public static void main(String[] args) {
                    A a = new A();
                    Thread t1 = new Thread1(a);
                    Thread t2 = new Thread2(a);
                    t1.start();
                    t2.start();
                }
            }
            class Thread1 extends Thread {
                private A a;
                public Thread1(A a) {
                    this.a = a;
                }
                public void run() {
                    a.fun1();
                }
            }

            class Thread2 extends Thread {
                private A a;
                public Thread2(A a) {
                    this.a = a;
                }
                public void run() {
                    a.fun2();
                }
            }
            class A {
                public synchronized void fun1() {
                    System.out.println("fun1进来了");
                    System.out.println("fun1()");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("fun1出去了");
                }
               
                public synchronized void fun2() {
                    System.out.println("fun2进来了");
                    System.out.println("fun2()");
                    System.out.println("fun2出去了");
                }
            }
            打印结果:fun1进来了
                  fun1()
                  fun1出去了
                  fun2进来了
                  fun2()
                  fun2出去了           
        对象如同锁,持有锁的线程才能在同步中执行,没有锁的线程,即使获取cpu的执行权,也进不去
        同步的前提:必须要有两个或以上的线程访问共享数据;必须是多个线程使用同一个锁(比如火车上的两个卫生间,就不是同一个锁)
        好处:解决了多线程安全问题
        弊端:多个线程都需要判断锁,较为消耗资源
        使用同步块还是使用同步方法呢?一般使用同步块,灵活
    静态同步方法:
        静态同步方法使用的锁是该方法所在类的class对象。即类名.class。
    单例设计模式:
        饿汉式:
            public class Single{
                //私有化构造器
                private Single(){}
                //创建对象
                private static final Single s = new Single();
                //提供方法,供外部使用
                public static Single getSingle()
                {
                    return s;
                }
            }
        懒汉式:
            public class Single(){
                private Single(){}
                private static Single s = null;
                public static Single getSingle()
                {
                    if(s == null)
                    {
                        synchronized(Single.class)
                        {
                            if(s == null)
                                s = new Single();
                        }
                    }
                }
            }
        懒汉式和饿汉式的区别:懒汉式的特点在于延迟加载,如果多个线程访问时,会出现安全问题。
                可以加同步来解决,用同步代码块和同步方法都行,但是同步方法稍微有些低效,
                所以一般用同步代码块,通过双重if判断来解决效率问题,同步锁是该类所属的字节码文件对象
    死锁:
        当两个线程相互等待对方释放同步监视器时就会发生死锁,Java虚拟机没有检测,也没有采取措施来处理死锁情况,
        所以多线程应该避免死锁的出现。一旦程序出现死锁,整个程序既不会发生异常,也不会有任何提示,
        只是所有线程都处于阻塞状态。一般这种情况发生在:同步中嵌套同步,但锁不同
        比如说:a线程锁定一个资源,同时想获取b线程的资源
            b线程锁定一个资源,同时想获取a线程的资源。
        举例:
            package com.itheima.lock;
            public class LockDemo {
                public static void main(String[] args) {
                    Thread t1 = new Thread1();
                    Thread t2 = new Thread2();
                    t1.start();
                    t2.start();
                }
            }
            class Thread1 extends Thread {
                public void run() {
                    synchronized (Object.class) {
                        System.out.println(Thread.currentThread().getName() + "...外层锁");
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        synchronized (String.class) {
                            System.out.println("haha,卡住了");
                        }
                    }
                }
            }
            class Thread2 extends Thread {
                public void run() {
                    synchronized (String.class) {
                        System.out.println(Thread.currentThread().getName() + "...外层锁");
                        synchronized (Object.class) {
                            System.out.println("haha,我也卡住了");
                        }
                    }       
                }
            }   
    线程通信:
        当多个线程访问同一资源,每个线程的实现功能不一样,而每个线程之间需要协调发展(两种线程交替执行)。
        比如说:
              老师:我们开始上课;
              学生A:老师等一下,我要去厕所;
              老师:OK,你快点,那我wait()了,等你回来notify我一下。
        线程通信的前提:同步环境!
        为了实现这种功能,需要借助Object类提供的wait(),notify(),notifyAll()这3个方法,这些方法不是Thread类的方法。
        这三个方法都使用在同步中,因为要对持有监视器的锁进行操作,所以要定义在同步中,因为只有同步才具有锁的概念
        为什么操作线程的方法要定义在Object类中?
            因为这些方法在操作同步中线程时都必须要标识它们所操作线程持有的锁,
            只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒
            也就是说:等待和唤醒必须是同一把锁
        而锁可以是任意对象,所以把可以被任意对象掉用的wait(),notify(),notityAll()定义在Object类中
        wait():声明了InterruptedException异常!在使用wait()时,还要使用try/catch。
        举例说明:
            package com.itheima.bank1;
            public class Bank {
                private double money;
                boolean flag = false;
                public Bank(double money)
                {
                    this.money = money;
                }
                /*取钱的方法*/
                public double drawMoney(double drawMoney)
                {
                    money = money - drawMoney;
                    return money;
                }
                /*存钱的方法*/
                public double saveMoney(double saveMoney)
                {
                    money = money + saveMoney;
                    return money;
                }
                /*查询余额*/
                public double getMoney()
                {
                    return money;
                }
            }
            package com.itheima.bank1;
            /*
             * 取钱操作的线程
             * */
            public class DrawThread extends Thread{
                private Bank b;
                private double drawMoney;
                public DrawThread(Bank b, double drawMoney, String name)
                {
                    super(name);
                    this.b = b;
                    this.drawMoney = drawMoney;
                }
                public void run()
                {
                    while(true)
                    {
                        synchronized(b)
                        {
                            if(!b.flag)
                            {
                                try {
                                    b.wait();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            if(b.getMoney() < drawMoney){
                                System.out.println("余额不足,当前余额是:" + b.getMoney());
                                break;
                            }
                            b.drawMoney(drawMoney);
                            System.out.println(Thread.currentThread().getName() + " 取款成功,取款金额是:" + drawMoney + ",账户余额:" + b.getMoney());
                            b.flag = false;
                            b.notify();
                        }
                    }
                }
            }
            package com.itheima.bank1;
            /*
             * 存钱操作的线程
             * */
            public class SaveThread extends Thread {
                private Bank b;
                private double saveMoney;
                public SaveThread(Bank b, double saveMoney, String name)
                {
                    super(name);
                    this.b = b;
                    this.saveMoney = saveMoney;
                }
                public void run()
                {
                    while(true)
                    {
                        synchronized(b)
                        {
                            if(b.flag)
                            {
                                try {
                                    b.wait();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            b.saveMoney(saveMoney);
                            System.out.println(Thread.currentThread().getName() + "存款成功,存款金额:" + saveMoney + ",当前余额:" + b.getMoney());
                            b.flag = true;
                            b.notify();
                        }
                    }
                }
            }
            package com.itheima.bank1;
            public class BankTest {
                public static void main(String[] args) {
                    Bank b = new Bank(5000);
                    new SaveThread(b, 200, "存钱线程...").start();
                    new DrawThread(b, 500, "取钱线程...").start();
                }
            }
    线程通信小结:
        1、使用wait()、notify()、notifyAll()方法可以完成线程间的通讯,可叫它们通讯方法;
        2、只能在同步环境下调用通讯方法;         
        3、只能使用监视器对象调用通讯方法;
        4、每个监视器对象都有一个线程监狱:执行监视器对象.wait()的线程会被关押到监视器对象的线程监狱中;
        5、若想释放出锁对象的线程监狱中的线程,那么需要调用监视器对象.notify()方法,
           该方法只能保证在监视器对象的线程监狱中释放出一个线程,但不能保证释放的是哪一个;
        6、还可以使用监视器.notifyAll()方法释放出监视器对象的监狱中关押的所有线程。
        7、被wait()了的线程不能自己恢复到就绪状态,只能等待其他线程调用同一监视器对象上的notify()或notifyAll()方法来唤醒。
        8、被wait()了的线程会释放监视器对象的对象锁,这样其他线程就可以进入他占用的同步环境。
        9、被唤醒的线程恢复到了就绪状态,当再次获取监视器对象的锁后会在wait()处向下运行。
    后台线程(守护线程):
       
    停止线程:
        如何停止线程呢?
            只有一种,run()结束
        怎么让run()结束呢?
            开启多线程运行,通常是通过循环结构,只要控制住循环,就可以让run()结束,也就是线程结束
        特殊情况:当线程处于冻结状态,线程就不会结束
        当没有指定的方式让线程从冻结恢复到运行状态,这是需要对冻结进行清除,强制让它恢复到运行状态中来,
        这样就可以操做标记让线程结束
        interrupt():将处于冻结状态的线程,强制的恢复到运行状态
    守护线程(后台线程):
        void setDaemon(boolean on):将该线程标记为守护线程或用户线程。
        将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
        该方法必须在启动线程前调用。
        后台线程的子线程,也是默认为后台线程!
          什么叫子线程?A线程的任务中启动了B线程,那么B是A的子线程。
        举例说明:
            package com.itheima;
            /*
             * 演示后台线程!
             */
            public class ServerThread {
                public static void main(String[] args) throws InterruptedException {
                    Thread t = new MyThread();
                    t.setDaemon(true);//在start()之前把t设置为后台线程
                    t.start();
                    for(int i = 0; i < 3; i++) {
                        System.out.println(i);
                        Thread.sleep(300);
                    }
                    System.out.println("bye-bye!");
                }
            }
            class MyThread extends Thread {
                public void run() {
                    for(int i = 0; i < 10; i++) {
                        Thread t = new ZiThread();
                        t.start();
                    }
                }
            }
            class ZiThread extends Thread {
                public void run() {
                    while(true) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            运行结果:
                0
                1
                2
                bye-bye!

    合并线程(join):
         void join():等待该线程终止。
         join()方法的作用:使当前线程等待该线程结束再向下运行。
         当A线程执行到了B线程的.join()方法时,A线程就会等待B线程执行完,才继续执行
         join()可以用来临时加入线程执行
         演示:
            package com.itheima;
            /*
             * 演示join()
             */
            public class JoinDemo {
                public static void main(String[] args) throws InterruptedException {
                    Thread t = new JoinThread();
                    t.start();
                    System.out.println("我要等待t结束");
                    t.join();//当前线程是主线程,主线程要等待t结束
                    System.out.println("\n终于等到t结束了!");
                }
            }
            class JoinThread extends Thread {
                public void run() {
                    for(int i = 0; i < 10; i++) {
                        System.out.print(i + " ,");
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            运行结果:
                我要等待t结束
                0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,
                终于等到t结束了!
    线程让步(yield):
        在以前使用sleep()的地方就可以尝试使用yield
        yield()方法的作用:说线程已经把最重要的工作做完了,告诉CPU可以切换给其他线程了。
        让步不同于阻塞:让步的线程没有进入阻塞状态,只是从运行状态到就绪状态!

------- android培训java培训、期待与您交流! ----------

分享到:
评论

相关推荐

    黑马程序员_张孝祥_Java多线程与并发库

    黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.

    黑马程序员_张孝祥_Java多线程与并发库 视频+代码+资料

    根据给定文件的信息,我们可以提炼出以下关于Java多线程与并发库的相关知识点: ### Java多线程基础 1. **线程的概念**:在Java中,线程是程序执行流的基本单元。一个标准的Java应用程序至少有一个线程,即主...

    黑马程序员_Java基础辅导班教程课件[第01期]第13天

    在"黑马程序员_Java基础辅导班教程课件[第01期]第13天"中,我们聚焦于Java编程语言的基础知识,这是一门面向初学者的课程,旨在帮助学员快速掌握Java开发的基本技能。第13天的课程通常会涵盖上一天(第12天)所学...

    01_黑马程序员_张孝祥_Java基础加强_课程价值与目标介绍.zip

    【标题】"01_黑马程序员_张孝祥_Java基础加强_课程价值与目标介绍.zip" 提供的是一门由黑马程序员机构推出的Java基础强化课程,由讲师张孝祥主讲,旨在深入讲解Java编程的基础知识并进行能力提升。 【描述】中提到...

    黑马程序员_毕向东_Java基础源码.rar

    这个名为“黑马程序员_毕向东_Java基础源码.rar”的压缩包文件,包含了丰富的Java基础源代码实例,对于初学者来说,是深入了解Java编程的良好资源。 一、Java基本语法 Java语言以其严格的类型检查和面向对象特性...

    黑马程序员-java多线程技术01

    本教程将聚焦于Java中的多线程技术,以“黑马程序员-java多线程技术01”为学习起点,探讨如何在Java中实现并管理线程。 首先,我们来理解什么是线程。线程是操作系统分配CPU时间的基本单元,一个进程中可以有多个...

    黑马程序员_(适合初学者入门的Java基础视频)

    "黑马程序员_(适合初学者入门的Java基础视频)"是一套专为初学者设计的Java基础教学课程,旨在帮助零基础的学习者逐步掌握Java编程的基本概念和技能。 该视频教程涵盖了Java的基础知识,包括: 1. **环境搭建**:...

    黑马程序员_Java基础辅导班教程课件[第01期]第10天

    在"黑马程序员_Java基础辅导班教程课件[第01期]第10天"中,我们聚焦于Java编程语言的基础知识,这是一门面向初学者的课程,旨在帮助学员快速掌握Java的核心概念。通过这个阶段的学习,学员将能够理解并运用Java的...

    黑马程序员_Java基础辅导班教程课件[第01期]第4天

    在"黑马程序员_Java基础辅导班教程课件[第01期]第4天"中,我们可以推测这是针对初学者的Java编程课程,旨在帮助学员掌握Java的基础知识。 在课程的第4天,可能讲解了以下核心概念: 1. **类(Class)**:`Demo.class...

    黑马程序员入学Java精华总结

    ### 黑马程序员入学Java精华总结 #### 一、Java概述与基础知识 1. **何为编程?** - 编程是指通过编写计算机能够理解的指令来解决问题或完成特定任务的过程。这些指令通常被组织成算法,并使用某种编程语言实现。...

    黑马程序员_从零开始征服Android之旅(第一季)源码和笔记

    《黑马程序员_从零开始征服Android之旅(第一季)源码和笔记》是一份全面的Android开发学习资源,旨在帮助初学者系统地掌握Android开发技术,实现从理论到实践的跨越。这份资料涵盖了一系列关键知识点,包括但不限于...

    黑马程序员–Java多线程讲解笔记

    Java多线程是Java编程中不可或缺的部分,它允许程序同时执行多个任务,提高了程序的效率和响应速度。本文主要探讨了多线程的概念、应用场景以及Java中创建线程的两种方式。 首先,进程和线程是理解多线程的基础概念...

    黑马程序员_毕向东最新经典Java基础视频

    根据提供的文件信息,我们可以推断出这是一套由知名IT教育机构“黑马程序员”出品、由讲师毕向东主讲的Java基础教学视频。由于实际视频内容无法直接获取,本篇将依据标题、描述以及部分标签内容,综合分析并展开相关...

    传智播客.黑马程序员《Java 基础入门》课后习题答案

    1、 面向对象、跨平台性、健壮性、安全性、可移植性、多线程性、动态性等。 2、 JRE(Java Runtime Environment,Java 运行时环境),它相当于操作系统部分,提供了 Java 程序运 行时所需要的基本条件和许多 Java ...

    java并发库高级应用源码--张孝祥

    Java并发库是Java编程中非常重要的一个领域,它为开发者提供了高效、安全的多线程编程工具。在《java并发库高级应用源码--张孝祥》中,我们将会深入探讨Java中的线程管理和并发控制策略,这对于我们理解和优化多线程...

    黑马程序员_2小时教你写一个安卓程序[第01天]课件源码

    在本课程中,“黑马程序员”将引导我们快速入门安卓应用程序的开发,这是一段为期两天的密集学习旅程,第01天的课程主要侧重于基础知识的建立和首个安卓程序的编写。通过这次学习,我们将了解到安卓开发环境的搭建、...

    多线程高新(黑马程序员)

    本文将深入探讨“多线程高新”这一主题,结合黑马程序员的课程内容,来阐述多线程的核心概念、优势、实现方式以及在实际应用中的注意事项。 首先,多线程是指在一个进程中同时执行多个线程,这些线程可以共享同一...

    黑马程序员入学Java知识——精华总结.doc

    Java内置了对多线程的支持,通过Thread类或实现Runnable接口可以创建并管理多个执行线程。 17. **网络编程**: Java提供了丰富的API进行网络通信,如Socket和ServerSocket类,用于客户端和服务器之间的连接。 ...

    黑马程序员入学Java知识(精华总结)

    ### 黑马程序员入学Java知识(精华总结) #### 一、Java概述与基础知识 ##### 1、何为编程? 编程是指使用计算机语言来编写指令,这些指令被计算机执行以完成特定任务的过程。通过编程,我们可以控制计算机的行为...

Global site tag (gtag.js) - Google Analytics