`
DavidIsOK
  • 浏览: 74067 次
社区版块
存档分类
最新评论

java 线程(一):基础篇

    博客分类:
  • java
阅读更多

                                                                              java中的多线程

java 线程基本介绍

1、进程与线程的区别

进程是指一个内存中运行的应用程序,每个进程都有一块独立的内存空间,一个进程包含一到多个线程。

每个线程都有他所属的进程,每个线程也就是该进程的一条执行路径,线程之间是高频率快速轮换执行的,‘同时’执行只是给人的感觉。

2Java当中线程一般有5中状态

创建状态:生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。

   就绪状态:当调用了线程的start方法,线程就进入就绪状态,调用start方法后线程不是立即执行的,只是开始排队等待执行了,具体什么时候执行得看CPU心情,当线程从等待或者休眠状态回来之后也是进入到就绪状态。

   运行状态:开始运行run()函数的代码,这时候就是运行状态啦。

   阻塞状态:线程正在运行的时候被暂停就是进入到阻塞状态,sleepsuspendwait都可以使线程进入阻塞状态。

  死亡状态:run()方法运行结束或者调用了线程的stop方法后,该线程就会死亡,对于已经死亡的线程无法使用start方法使其进入就绪状态。

 

java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口。

对于直接继承Thread的类来说,代码大致框架是:

class 类名 extends Thread{
方法1;
方法2;
…
public void run(){
// other code…
}
属性1;
属性2;
…
 
}

 

先看一个简单的例子:

package com.hxw.Threads;
 
class ThreadTest {
   
    /**
     * 观察直接调用run()和用start()启动一个线程的差别
     * @author HaiCheng
     * @param args
     * @throws Exception
     */
    publicstaticvoid main(String[] args){
       Thread r=new ThreadDemo("直接调用run执行");
       r.run();
        Thread t1=new ThreadDemo("线程一");
        t1.start();
        Thread t2=new ThreadDemo("线程二");
        t2.start();
        for(int i=0;i<10;i++){
          System.out.println("主线程执行------>"+i);
        }
    }
   
    publicstaticclass ThreadDemo extends Thread{
       private String ThreadName;
       public ThreadDemo(String s){
          this.ThreadName=s;
       }
        @Override
        publicvoid run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(this.getThreadName()+"执行------>"+i);
            }
        }
      public String getThreadName() {
         returnThreadName;
      }
    }
}

 

runstart的区别

1 start

start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到spu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。

2 run

run方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。

 

通过实现Runnable接口:

大致框架是:

class 类名 implements Runnable{
方法1;
方法2;
…
public void run(){
// other code…
}
属性1;
属性2;
…
 
} 

 

来先看一个小例子吧:

/**
 * @author Rollen-Holt 实现Runnable接口
 * */
class hello implements Runnable {
    public hello() {
    }
    public hello(String name) {
        this.name = name;
    }
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "运行     " + i);
        }
    }
    public static void main(String[] args) {
        hello h1=new hello("线程A");
        Thread demo= new Thread(h1);
        hello h2=new hello("线程B");
        Thread demo1=new Thread(h2);
        demo.start();
        demo1.start();
    }
     private String name;
}

 

【可能的运行结果】:

线程A运行     0

线程B运行     0

线程B运行     1

线程B运行     2

线程B运行     3

线程B运行     4

线程A运行     1

线程A运行     2

线程A运行     3

线程A运行     4

 

关于选择继承Thread还是实现Runnable接口?

其实Thread也是实现Runnable接口的

class Thread implements Runnable {
    //…
public void run() {
        if (target != null) {
             target.run();
        }
        }
}

 

ThreadRunnable的区别:

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

/**
 * @author Rollen-Holt 继承Thread类,不能资源共享
 * */
class hello extends Thread {
    public void run() {
        for (int i = 0; i < 7; i++) {
            if (count > 0) {
                System.out.println("count= " + count--);
            }
        }
    }
    public static void main(String[] args) {
        hello h1 = new hello();
        hello h2 = new hello();
        hello h3 = new hello();
        h1.start();
        h2.start();
        h3.start();
    }
    private int count = 5;
} 

 

【运行结果】:

count= 5

count= 4

count= 3

count= 2

count= 1

count= 5

count= 4

count= 3

count= 2

count= 1

count= 5

count= 4

count= 3

count= 2

count= 1

大家可以想象,如果这个是一个买票系统的话,如果count表示的是车票的数量的话,说明并没有实现资源的共享。

我们换为Runnable接口

 

class MyThread implements Runnable{
 
    private int ticket = 5;  //5张票
 
    public void run() {
        for (int i=0; i<=20; i++) {
            if (this.ticket > 0) {
                System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
            }
        }
    }
}
public class lzwCode {
     
    public static void main(String [] args) {
        MyThread my = new MyThread();
        new Thread(my, "1号窗口").start();
        new Thread(my, "2号窗口").start();
        new Thread(my, "3号窗口").start();
    }
}

 

【运行结果】:

count= 5

count= 4

count= 3

count= 2

count= 1

 

总结一下吧:

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

 

所以,本人建议大家尽量实现接口。

/**
 * @author Rollen-Holt
 * 取得线程的名称
 * */
class hello implements Runnable {
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }
 
    public static void main(String[] args) {
        hello he = new hello();
        new Thread(he,"A").start();
        new Thread(he,"B").start();
        new Thread(he).start();
    }
}

 

【运行结果】:

A

A

A

B

B

B

Thread-0

Thread-0

Thread-0

说明如果我们没有指定名字的话,系统自动提供名字。

提醒一下大家:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。

 

java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实际在就是在操作系统中启动了一个进程。

二、>线程常用方法解析

1.  判断线程是否启动:

方法解析:在这里提一下上面的

currentThread()方法,返回对当前正在执行的线程对象的引用。

isAlive(),测试线程是否处于活动状态。如果线程已经启动且尚未终止,则为活动状态。

package com.hxw.Threads;
 
/**
 * @author Rollen-Holt 判断线程是否启动
 * */
class hello implements Runnable {
    publicvoid run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }
 
    publicstaticvoid main(String[] args) {
        hello he = new hello();
        Thread demo = new Thread(he);
        System.out.println("线程启动之前---》" + demo.isAlive());
        demo.start();
        System.out.println("线程启动之后---》" + demo.isAlive());
        System.out.println("线程启动之后后 ---》" + demo.isAlive());
        System.out.println("线程启动之后后 ---》" + demo.isAlive());
        System.out.println("线程启动之后后 ---》" + demo.isAlive());
        System.out.println("线程启动之后后 ---》" + demo.isAlive());
        System.out.println("线程启动之后后 ---》" + demo.isAlive());
        System.out.println("线程启动之后后 ---》" + demo.isAlive());
        System.out.println("线程启动之后后 ---》" + demo.isAlive());
 
    }
}

 

 

【运行结果】

线程启动之前---false

线程启动之后---true

线程启动之后后 ---true

Thread-0

线程启动之后后 ---true

线程启动之后后 ---true

Thread-0

线程启动之后后 ---true

Thread-0

线程启动之后后 ---true

线程启动之后后 ---false

线程启动之后后 ---false

从上面的例子来看:确实是有主线程和子线程在运行的,而且主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。这个叫非守护线程。

上面的例子也表示出了在run方法执行完成后,线程就死亡了,只是由于主线程和子线程之间同步问题,如果想原文的那样在demo.start()后只打印一个alive()是有问题的。

 

2.  线程的强制执行:thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程AJoin()方法即A.jion(),直到线程A执行完毕后,才会继续执行线程B

t.join();      //使调用线程 t 在此之前执行完毕。

t.join(1000);  //等待 t 线程,等待时间是1000毫秒

/**
     * @author Rollen-Holt 线程的强制执行
     * */
    class hello implements Runnable {
        public void run() {
            for (int i = 0; i < 3; i++) {
                System.out.println(Thread.currentThread().getName());
            }
        }
     
        public static void main(String[] args) {
            hello he = new hello();
            Thread demo = new Thread(he,"线程");
            demo.start();
            for(int i=0;i<50;++i){
                if(i>10){
                    try{
                        demo.join();  //强制执行demo()
                    }catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("main 线程执行-->"+i);
            }
        }
    }

 

【运行的结果】:

main 线程执行-->0

main 线程执行-->1

main 线程执行-->2

main 线程执行-->3

main 线程执行-->4

main 线程执行-->5

main 线程执行-->6

main 线程执行-->7

main 线程执行-->8

main 线程执行-->9

main 线程执行-->10

线程

线程

线程

main 线程执行-->11

main 线程执行-->12

main 线程执行-->13

...

 

3.线程的休眠:sleep() 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),

sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。

package com.hxw.Threads;
 
import java.text.SimpleDateFormat;
 
/**
 * @author Rollen-Holt 线程的休眠
 * */
class hello implements Runnable {
    publicvoid run() {
        for (int i = 0; i < 3; i++) {
            try {
                Thread.sleep(2000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + i+"   "+(new SimpleDateFormat("yyyy-MM-dd   hh:mm:ss").format(new java.util.Date())));
        }
    }
 
    publicstaticvoid main(String[] args) {
        hello he = new hello();
        Thread demo = new Thread(he, "线程");
        demo.start();
    }
}

 

 

【运行结果】:(结果每隔2s输出一个)

线程0   2014-08-16   06:06:21

线程1   2014-08-16   06:06:23

线程2   2014-08-16   06:06:25

 

4.线程的优先级:

与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。

线程的优先级用1-10之间的整数表示,数值越大优先级越高,默认的优先级为5,主线程的优先级也是5

在一个线程中开启另外一个新线程,则新开线程称为该线程的子线程,子线程初始优先级与父线程相同。
可以用下面方法设置和返回线程的优先级。
public final void setPriority(int newPriority)
设置线程的优先级。
public final int getPriority()
返回线程的优先级。
 newPriority
为线程的优先级,其取值为110之间的整数,也可以使用Thread类定义的常量来设置线程的优先级,这些常量分别为:Thread.MIN_PRIORITYThread.NORM_PRIORITYThread.MAX_PRIORITY,它们分别对应于线程优先级的1510,数值越大优先级越高。当创建Java线程时,如果没有指定它的优先级,则它从创建该线程那里继承优先级。

/**
 * @author Rollen-Holt 线程的优先级
 * */
class hello implements Runnable {
    public void run() {
        for(int i=0;i<5;++i){
            System.out.println(Thread.currentThread().getName()+"运行"+i);
        }
    }
 
    public static void main(String[] args) {
        Thread h1=new Thread(new hello(),"A");
        Thread h2=new Thread(new hello(),"B");
        Thread h3=new Thread(new hello(),"C");
        h1.setPriority(8);
        h2.setPriority(2);
        h3.setPriority(6);
        h1.start();
        h2.start();
        h3.start();
         
    }
} 

 

【运行结果】:

A运行0

A运行1

A运行2

A运行3

A运行4

B运行0

C运行0

C运行1

C运行2

C运行3

C运行4

B运行1

B运行2

B运行3

B运行4

5. 线程的礼让: yield()

通过调用yield方法,线程可能自动的转发控制权给其他等待的线程,一般情况,在等待其他具有相同优先级的线程产生的某个结果是,线程会转让控制权。考虑如下情形,多线程情况下,有一个可读写文件由多个线程来读写操作,多线程情况下,为了保证数据一致性,在读写访问时都将锁住这个文件,读写线程可能都运行在相同的优先级,现在拥有文件锁的线程可能会周期性的将控制权转让给另一个与之竞争的线程。

需要注意的是,yield()方法对JVM来说是“提示”,而不是强制要求,也没有结束。JVM无法保证线程调度的确定性,这一点我们会在下面的例子展示出来,除此之外也不能确定这个提示是让更低级的线程获得控制权还是同级的线程获得控制权,尽管大多数情况下是同级线程获得控制权的。这个方法比较不稳定,一般不常用。它所表达的意思口语化一点就是:“我急获得了足够的CPU时间,想让其他线程有机会运行,我将在一段时间后运行剩余的代码”,这与sleep方法不一样,sleep的意思是:“在n毫秒的时间内我不想运行,就算没有其他线程想运行,也别让我运行”。

package com.hxw.Threads;
 
/**
 * @author Rollen-Holt 线程的优先级
 * */
class hello2 implements Runnable {
    synchronized publicvoid run() {
        for(int i=0;i<12;++i){
            System.out.println(Thread.currentThread().getName()+"运行"+i);
            if(i==3){
                Thread.currentThread().yield();
                System.out.println(Thread.currentThread().getName()+"将自己的线程礼让出来了");
            }
        }
    }
 
    publicstaticvoid main(String[] args) {
        Thread h1=new Thread(new hello2(),"A");
        Thread h2=new Thread(new hello2(),"B");
        h1.start();
        h2.start();
        
    }
}

 

A运行0

B运行0

A运行1

B运行1

A运行2

B运行2

A运行3

A将自己的线程礼让出来了

A运行4

A运行5

A运行6

A运行7

A运行8

A运行9

A运行10

A运行11

A运行12

B运行3

B将自己的线程礼让出来了

B运行4

B运行5

B运行6

B运行7

B运行8

B运行9

B运行10

B运行11

B运行12

 

相信读者看完上面的结果想“呵呵!”了,A真不客气,都说将自己的线程礼让出来了还愣是把自己运行完了才把控制权交给B,这就是yiel()方法的“提示”转让。当然有些时候还会准确的让出控制权的。

6.线程的中断(打扰)

中断的原理:Java中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理中断。这好比是家里的父母叮嘱在外的子女要注意身体,但子女是否注意身体,怎么注意身体则完全取决于自己。

Java中断模型也是这么简单,每个线程对象里都有一个boolean类型的标识(不一定就要是Thread类的字段,实际上也的确不是,这几个方法最终都是通过native方法来完成的),代表着是否有中断请求(该请求可以来自所有线程,包括被中断的线程本身)。例如,当线程t1想中断线程t2,只需要在线程t1中将线程t2对象的中断标识置为true,然后线程t2可以选择在合适的时候处理该中断请求,甚至可以不理会该请求,就像这个线程没有被中断一样。

关于线程的中断/打扰有三个重要方法,interrupt,isInterrupted,interrupted

interrupt: 中断(打扰)线程。

interrupted:静态方法,测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(即线程状态为非中断状态,而其实已经是终端状态,知识没有了这个终端标识了而已)。

isInterrupted: 测试线程是否已经中断。这个方法不是静态的,调用是需要对象引用,而且这个方法不会清空中断标志。

        当另一个线程通过调用 Thread.interrupt() 中断一个线程时,会出现以下两种情况之一。一种情况正常的话会设置该线程的终端状态,但是如果那个线程在执行一个低级可中断阻塞方法,例如Thread.sleep() Thread.join()  Object.wait(),那么它将取消阻塞并抛出 InterruptedException

注意:j2se 1.2开始,stop,suspend,resume方法就已经不提倡使用了,因为他们容易造成死锁。

摘录自一本书:反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

这个中断的例子匆忙举出一个是不太准确的,后面会专门写一个文章来测试这个用法。

7.  守护线程和非守护线程

JVM中存在两种线程:用户线程和守护线程。

   所谓的守护线程,是指用户程序在运行的时候后台提供的一种通用服务的线程,比如用于垃圾回收的

垃圾回收线程。这类线程并不是用户线程不可或缺的部分,只是用于提供服务的"服务线程"

   基于这个特点,当虚拟机中的用户线程全部退出运行时,守护线程没有服务的对象后,JVM也就退出了,反之还有任意一个用户线程在,JVM都不会退出。

我们如何开始一个自定义的守护进程呢?正如上述代码一样,答案很简单,就是在Thread.start()方法之前使用setDaemon(true)方法,通过此方法将Thread类中的boolean daemon=true;JVM就会将该线程归为守护线程

说完了守护线程如何产生和特点,下面简要的谈谈使用守护线程应该注意的地方。

            1thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个异常。你不能把正在运行

                   的常规线程设置为守护线程。 

            2、在守护线程中产生的线程也是守护线程。(这点读者可结合工具自己验证)

            3、我们自己产生的守护线程应该避免访问一些类似于文件、数据库等固有资源,因为由于JVM没有用户

                 线程之后,守护线程会马上终止。

这一个不做例子,因为在eclipse查看不了jvm退出后其他用户线程的动作,所以查看起来比较复杂,需要用jvisualvm.exe 来看这一点会再另外写一篇文章阐述。

   8.     关于非常重要的waitnotify方法我在下一篇讲线程同步的时候再写

 

以上是线程的基本用法,下一篇是关于线程的同步,因为我写的比较详细,也参考了很多资料,希望能把即使比较偏的知识点也囊括进来,如果文章有什么问题和要改进的地方,请提出来大家讨论,我会一一回复,我非常想交一些技术上的朋友。

分享到:
评论
2 楼 DavidIsOK 2014-08-22  
嗯嗯,这么说也是对的,因为实质是因为不是同一个对象的问题,就使用来说,更表层一点的就表现成了不共享的问题
1 楼 tiwenzhuanyong 2014-08-21  
LZ在说Thread和Runnable的区别时有误:
在使用implements接口方式时,如果是这样调用
public class lzwCode {  
    
    public static void main(String [] args) {  
        MyThread my1 = new MyThread();  
        MyThread my2 = new MyThread();  
        MyThread my3 = new MyThread();  
        new Thread(my1, "1号窗口").start();  
        new Thread(my2, "2号窗口").start();  
        new Thread(my3, "3号窗口").start();  
    }  
}  

一样会得到类似这样的结果
【运行结果】:
count= 5
count= 4
count= 3
count= 2
count= 1
count= 5
count= 4
count= 3
count= 2
count= 1
count= 5
count= 4
count= 3
count= 2
count= 1
同样,在使用extends方式时,如果这样调用;
public static void main(String[] args) {  
    hello h1 = new hello();  
    new Thread(h1).start();
    new Thread(h1).start();
    new Thread(h1).start();
}  

得到的是这样的结果:
count= 5
count= 4
count= 3
count= 2
count= 1
所以这不是implements和extends方式的区别,而是线程启动时操作的是否是同一个对象造成的。

相关推荐

    3796 i-FRAME 安装、操作和维护手册

    3796 i-FRAME 安装、操作和维护手册

    我的visio画图 资源备用

    我的visio画图

    NPOI是指构建在POI 3.x版本之上的一个程序

    NPOI可以在没有安装Office的情况下对Word或Excel进行读写,NPOI是一个开源的C#读写Excel、WORD等微软OLE2组件文档的项目

    基于STM32F103C8单片机设计-旋转编码器数码管显示程序KEIL工程源码.zip

    STM32学习软件编程资料,STM32F103C8单片机经典外设应用设计实例软件源代码,KEIL工程文件,可供学习参考。

    VoLTE高丢包优化指导书.xlsx

    VoLTE高丢包优化指导书

    LTE容量优化高负荷小区优化指导书.docx

    5G通信行业、网络优化、通信工程建设资料

    中国移动无线、传输专业项目全生命周期、建设期、施工期控制标准.docx

    5G通信行业、网络优化、通信工程建设资料

    基于Springboot+Vue校园周边美食探索及分享平台毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    基于Springboot+Vue善筹网(众筹)前后台实现设计-毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    203ssm-mysql-jsp 包头市交通管理局路况查询系统.zip(可运行源码+数据库文件+)

    该课题主要是以SpringMVC模式运行的,采用了mysql数据库进行数据的管理,掌握并且熟练使用百度API相关技术。系统分为了管理员用户和一般用户,主要有以下模块: 管理员用户: 1.实时路况管理:实时路况的信息采用了百度地图进行直观的管理,利用了GIS相关技术进行管理,能够让用户方便的第一时间查看到相应的地图信息,以及实时路况信息。 2.投诉留言管理:实现了对投诉留言信息的查看和回复。 3.系统信息设置:实现了系统的访问数据的统计,以及针对系统的管理员 用户和管理员密码进行管理。 4.用户信息管理:管理了一般用户的基本信息情况,针对用户的资料进行修改管理。 一般用户: 1.用户资料管理:实现了用户个人的资料信息管理。 2.路况信息查看:实现了对路径的实时信息的查看,某个路段在某时间的交通情况的查看,以三种情况代表路况情况(拥挤、缓行和畅通) 3.路况分析:采用了折线图,分析每天或者某个月的路况信息,以折线图形式直观展示。该功能采用jFreeChart库实现。 4.留言发布:针对一些路况信息,进行留言反馈,并能查看管理员反馈信息。

    施工现场安全技术交底模板.doc

    5G通信行业、网络优化、通信工程建设资料。

    GSM室分优化掉话专题总结报告.docx

    5G通信、网络优化与通信建设

    通信线缆基本理论.docx

    5G通信行业、网络优化、通信工程建设资料。

    node-v12.20.1-sunos-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    199-数据安全治理的思考与规划-论剑.pdf

    199-数据安全治理的思考与规划-论剑.pdf

    SPVLoc: Semantic Panoramic Viewport Matching for 6D Camera Local

    SPVLoc: Semantic Panoramic Viewport Matching for 6D Camera Localization in Unseen Environments

    基于Springboot+Vue校园资料分享平台毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    基于Springboot+Vue大学生科创项目在线管理系统的设计-毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    基于微信平台的报刊订阅小程序的设计与实现ssm后端毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    计算机网络实验报告-实验七:RIP、OSPF动态路由协议

    实验内容七:RIP、OSPF动态路由协议 实验目的:配置RIP、OSFP动态路由 实验任务1:RIP路由配置实验 (1) 添加三台2811型号路由器,为每台路由器添加网络接口模块 先关闭路由器电源,电源开关如下图。 ( 实际操作中,为确保电路安全,只有关机后,才可以在路由器中插入新的网络模块卡,类似往计算机中插入网卡。) 在三台路由器上均添加模块NM-2FE2W,拖拽右下角模块到左上方路由器插槽中,如下图所示。(NM-2FE2W有2个 快速以太网接口)。 插入新模块后,再重新开启路由器。 (2) 添加三台PC机,所有设备之间用交叉线连接,配置网络接口IP地址。 按照拓扑图中地址设置, 配置路由器各网络接口IP地址、子网掩码。 配置PC机各网络接口IP地址、子网掩码、默认网关。 (3)分别查看三台路由器的路由表 Router# show ip route 三个路由表中,只显示了每台路由器直接连接的网络地址和接口。 (4)在三台路由器上,分别配置动态RIP路由协议,自动更新路由表。 R1路由器示例: Router>enable Router#config

Global site tag (gtag.js) - Google Analytics