线程是什么意思,线程数越多越好吗

1. 基础介绍

线程有四种创建方式,但是我只记录两种,还有的创建方式是通过实现Callable接口,并且重写其中的call方法(有一点要注意,就是只有线程执行完毕才能收到返回值);

程序:是为了完成某种任务而使用某一个编程语言编写的一组指令的集合;(可以理解成代码)进程:是指程序的执行过程,或是正在运行的程序,属于一个动态的过程;线程:由进程进一步细化,是一个程序内部的一条执行途径(比如在Java中一个main函数其实就是一个线程,它是从main开始执行);线程分为守护线程和用户线程;守护线程(如垃圾回收机制的线程)用来服务用户线程;多线程:指的就是一个进程同时有多个线程并行执行;并行:多个CPU执行多个任务;并发:一个CPU执行多个任务;(详细的看一看操作系统,通过时间片完成)

注意:一个简单的Java.exe应用程序,运行的话,其中至少有三个线程;一个main(主线程),一个gc()垃圾回收机制(垃圾回收线程,它的垃圾回收是自动的),还有一个异常处理线程;

2.线程的创建和使用

第一种创建线程的方法

//自己创建一个类继承Thread类;然后就重写其中的run方法;run方法中写你要执行的动作;

class testThread extends Thread {

// 重写run方法

@Override

public void run() {

for (int i = 0; i < 10; i++) {

System.out.println("线程:"+Thread.currentThread().getName()+":" + i);

}

}

}

public class ThreadCreate {

public static void main(String[] args) {

// 创建一个对象调用start方法,不过这个方法是Thread中的;

testThread t = new testThread();

t.start();

for (int j = 0; j < 1000; j++) {

System.out.println("主线程:"+Thread.currentThread().getName()+":" + j);

}

}

}

它的结果就证明了线程之间的运行是并发的,就是通过时间片来管理进行;不是一种顺序执行;

完整的线程基础介绍,看完就基本了解了什么是线程

Thread中的常用方法:

完整的线程基础介绍,看完就基本了解了什么是线程yeild()方法运行演示:(每次运行到i%2==1的时候就会释放子线程,但是有时候cpu的运行权又会被子线程重新抢回去 )

完整的线程基础介绍,看完就基本了解了什么是线程join()方法运行演示:(在主线程中调用子线程,直到子线程运行完,才会重新调用主线程)

完整的线程基础介绍,看完就基本了解了什么是线程

2.第二种创建线程的方法

就是指写一个类实现Runnable接口,然后重写其中的run方法;需要执行的操作写在run方法中;

public class RunableText implements Runnable {

//重写Runnable中的方法,

@Override

public void run() {

for (int i = 0; i < 10; i++) {

/*

由于这个方法已经不是Thread类中的方法,而是Runnable

接口中的方法,在Runnable中没有getName等方法,所以只能直接通过Thread调用;

主要还是currentThread()是静态的返回一个Thread对象;

*/

System.out.println(Thread.currentThread().getName() + ":" + i);

}

}

public static void main(String[] args) {

// 创建一个实现Runnable接口的对象

RunableText runableText = new RunableText();

// 创建一个Thread对象,然后就是放入到Thread的构造方法中生成一个线程;

Thread thread = new Thread(runableText);

// 由于通过Thread类已经生成了一个线程;,于是就可以调用Thread线程中的方法;

thread.setName("子线程");

thread.start();//开启线程

Thread.currentThread().setName("主线程");

for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName() + ":" + i);

}

}

}

上述程序运行结果:

完整的线程基础介绍,看完就基本了解了什么是线程

2. 线程的调度

注意: 在Java中线程的优先级并非绝对的,尝试之后发现并非优先级高就可以先全部执行,只能说优先级越高,那么执行的概率越大;

线程的各种优先级,如下图:(不同的优先级就会有不同的执行顺序;)第一个是最低的优先级,第二个是默认优先级,第三个是最高优先级;

完整的线程基础介绍,看完就基本了解了什么是线程

2.定义优先级的方法

完整的线程基础介绍,看完就基本了解了什么是线程

完整的线程基础介绍,看完就基本了解了什么是线程

上述代码执行的结果:

完整的线程基础介绍,看完就基本了解了什么是线程

3. 线程的生命周期

线程的生命周期,是主要记录在线程的类Thread.State,

1.

完整的线程基础介绍,看完就基本了解了什么是线程

2.

完整的线程基础介绍,看完就基本了解了什么是线程

3.

完整的线程基础介绍,看完就基本了解了什么是线程

4.

完整的线程基础介绍,看完就基本了解了什么是线程

完整的线程基础介绍,看完就基本了解了什么是线程

完整的线程基础介绍,看完就基本了解了什么是线程

按照上面的图片稍作解释;

第一个new状态,就是指线程刚刚创立,还没有调用start方法的时候;

第二个 RUNNABLE,则是指线程目前处于可运行状态,在等待需要的资源,就像是操作系统中的就绪;

第三个 BLOCKED,这个不是很理解,等继续学习之后再看看吧,但是在网上看来一下,大概就是类似于阻塞;

第四个 WAITING,这个大概就是理解为使用了wait()方法进入等待状态之后;

第五个TIMED_WAITING,是指使用wait(long)方法,进入等待状态后;

TERMINATED;最后一个就是线程已经终结;生命到了尽头;

4. 线程的同步

有时候,比如卖票的时候,如果只是使用上面的基础线程肯定是不能达到要求的,会出现重票,甚至是负票的现象;如下面的问题程序:

public class RunTicket implements Runnable {

private static int ticket = 100;

@Override

public void run() {

while (ticket > 0) {

System.out.println(Thread.currentThread().getName() + ":" + ticket);

ticket–;

}

}

public static void main(String[] args) {

RunTicket run = new RunTicket();

Thread thread1 = new Thread(run);

Thread thread2 = new Thread(run);

Thread thread3 = new Thread(run);

thread1.setName("窗口1");

thread2.setName("窗口2");

thread3.setName("窗口3");

thread1.start();

thread2.start();

thread3.start();

}

}

运行结果:

完整的线程基础介绍,看完就基本了解了什么是线程

那么为什么出票会出现重复?

首先可以知道线程的运行顺序是不规则的,你不能知道cpu并发线程中的哪些线程会运行,哪些线程会停止,当第一个线程对象的ticket(ticket=100)没有运行ticket–时,第二个线程就已经取到了ticket的值(这时ticket=100),这时就会发生所谓的重票现象,因为他们共用一个对象run,所以也就共用一个ticket;

解决办法:

同步代码块,使用synchronized对需要同步的代码进行修饰;在这里我们可以直接同步那些使用了ticket的代码,意思就是只有一个对线程对象可以使用,这就是使用同步监视器(或称锁)的方法进行同步;

public class RunTicket implements Runnable {

private int ticket = 100;

//创建一个公用的对象,当锁

Kmdog kmdog = new Kmdog();

@Override

public void run() {

while (true) {

//当然这里就是使用锁的地方,锁也不一定非要这样写,有时候可以用this,考虑使用当前类来做锁;

synchronized (kmdog) {

if (ticket > 0) {

System.out.println(Thread.currentThread().getName() + ":" + ticket);

ticket–;

} else {

break;

}

}

}

}

public static void main(String[] args) {

RunTicket run = new RunTicket();

Thread thread1 = new Thread(run);

Thread thread2 = new Thread(run);

Thread thread3 = new Thread(run);

thread1.setName("窗口1");

thread2.setName("窗口2");

thread3.setName("窗口3");

thread1.start();

thread2.start();

thread3.start();

}

}

class Kmdog {

}

最重要的是要使用公共的锁;

运行结果:

完整的线程基础介绍,看完就基本了解了什么是线程

2. 通过同步方法;也可以达到上述的要求;详细请百度,不做赘述;

杂记,现学即现记(以后把所有东学西记的东西全部总结起来)

百度的时候无意中看到,在子类的构造方法中可以通过super调用父类的普通方法,尝试了一下还真的可以;又get到了一个新东西;

父类中的方法要是没有throws异常,那么子类就无法直接throws异常;为什么static不能修饰局部变量,因为它修饰的是全局变量;线程组:在java.lang.ThreadGroup类是用来定义一个线程组的;一个管理线程的类;每个线程都拥有自己独立的栈和程序计数器;多个线程共享一个进程中的方法区;接口与接口之间必须要通过extends继承,而不能通过implements实现;只有类才能实现接口;我发现其实所有继承了Runnable接口的B接口,都可以通过实现B,来创建线程;比如(RunnableFuture);

本文地址:https://www.cknow.cn/archives/30042

以上内容源自互联网,由百科助手整理汇总,其目的在于收集传播生活技巧,行业技能,本网站不对其真实性、可靠性承担任何法律责任。特此声明!

如发现本站文章存在版权问题,烦请提供版权疑问、侵权链接、联系方式等信息发邮件至candieraddenipc92@gmail.com,我们将及时沟通与处理。