java笔记五:多线程的使用

  以前学习基础的时候学习了一段时间的多线程,上课的时候老师也讲过一遍,那时候感觉学的似懂非懂。因为到现在很长一段时间没有用到多线程的知
识,所以现在基本上忘了差不多了。但是下个星期要面试了,所以今天特意又研究了一下多线程,免得被问到多线程问题时什么都不记得了那就麻烦了。现在对
java比较熟悉了,所以再一次学习多线程知识,感觉没有那么难了(记得刚接触多线程的时候,感觉非常吃力)。

  首先讲一下进程和线程的区别:

    进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。

    线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。

    线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。

    多进程是指操作系统能同时运行多个任务(程序)。

    多线程是指在同一程序中有多个顺序流在执行。

在java中创建一个线程有两种方法:

    ①实现java.lang.Runnable接口,重写run()方法,启动:new Thread(this).start()。

 1 package com.thread;
 2
 3 public class ThreadTest1 {
 4     public static void main(String[] args) {
 5         Runnable1 r = new Runnable1();
 6         //r.run();并不是线程开启,而是简单的方法调用
 7         Thread t = new Thread(r);//创建线程
 8         //t.run(); //如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
 9         t.start(); //线程开启
10         for (int i = 0; i < 100; i++) {
11             System.out.println(“main:”+i);
12         }
13     }
14 }
15 class Runnable1 implements Runnable{
16     public void run() {
17         for (int i = 0; i < 100; i++) {
18             System.out.println(“Thread—–:”+i);
19         }
20     }
21 }

  要注意的是:

    1.r.run()并不是启动线程,而是简单的方法调用。

    2.Thread也有run()方法,如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。

    3.并不是一启动线程(调用start()方法)就执行这个线程,而是进入就绪状态,什么时候运行要看CUP。

    ②继承java.lang.Thread类,重写run()方法。

 1 package com.thread;
 2
 3 public class TestThread2 {
 4     public static void main(String[] args) {
 5         Thread1 t = new Thread1();
 6         //t.run(); //这里也不能直接调用方法
 7         t.start();
 8         for (int i = 0; i < 100; i++) {
 9             System.out.println(“main:”+i);
10         }
11     }
12 }
13
14 //尽量使用实现Runnnable接口,因为接口比较灵活
15 class Thread1 extends Thread{
16     @Override
17     public void run() {
18         for (int i = 0; i < 100; i++) {
19             System.out.println(“Thread—–:”+i);
20         }
21     }
22 }

虽然两种方法都可行,但是最好还是用第一种方法,因为使用接口灵活性好,java中时单继承、多实现。

Thread类中常用的方法有:

  ①sleep(long millis): 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。

 1 package com.thread;
 2 import java.util.Date;
 3 /*
 4   sleep()指在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
 5   @author Administrator
 6
 7  */
 8 public class SleepTest {
 9     public static void main(String[] args) {
10         Thread2 t = new Thread2();
11         t.start();
12         try {
13             Thread.sleep(10000); //主线程睡眠10秒钟
14         } catch (InterruptedException e) {
15             e.printStackTrace();
16         }
17         //主线程睡眠10秒钟后结束t线程
18         //t.interrupt(); //这种结束方式比较粗暴,如果t线程打开了某个资源还没来得及关闭也就是run方法还没有执行完就强制结束线程,会导致资源无法关闭
19         //t.stop();也是结束某个线程,这种方式比interrupt()更粗暴
20         t.flag = false;
21     }
22 }
23 class Thread2 extends Thread{
24     boolean flag = true; //用这种方式结束线程很不错,用一个变量控制run方法什么时候不再执行,不会出现run方法没有执行完毕就结束
25     @Override
26     public void run() { //run方法一结束,整个线程就终止了
27         while(flag){
28             System.out.println(“—“+new Date()+”—“);
29             try {
30                 sleep(1000);
31             } catch (InterruptedException e) {
32                 return;
33             }
34         }
35     }
36 }

 

  ②join():指等待t线程终止。也可以理解为将t线程合并到当前线程来,等待t线程结束后再往下执行。相当于方法调用

 1 package com.thread;
 2
 3 import java.util.Date;
 4
 5 /
 6   t.join()方法指等待t线程终止。也可以理解为将t线程合并到当前线程来,等待t线程结束后再往下执行。相当于方法调用
 7  */
 8 public class TestJoin {
 9     public static void main(String[] args) {
10         Thread t = new Thread3(“abc”);
11         t.start();
12         for (int i = 0; i < 20; i++) {
13             System.out.println(“我是main线程”);
14             if(i==10){
15                 try {
16                     t.join();
17                 } catch (InterruptedException e1) {
18                     // TODO Auto-generated catch block
19                     e1.printStackTrace();
20                 }
21             }
22             try {
23                 Thread.sleep(1000);
24             } catch (InterruptedException e) {
25                 e.printStackTrace();
26             }
27         }
28     }
29 }
30 class Thread3 extends Thread{
31     public Thread3(String s) { //给该线程取一个名字,用getName()方法可以去到该名字
32         super(s);
33     }
34     @Override
35     public void run() {
36         for (int i = 0; i < 20; i++) {
37             System.out.println(“我是”+getName()+”线程”);
38             try {
39                 sleep(1000);
40             } catch (InterruptedException e) {
41                 e.printStackTrace();
42             }
43         }
44     }
45 }

运行该程序结果为:

 1 我是main线程
 2 我是abc线程
 3 我是main线程
 4 我是abc线程
 5 我是main线程
 6 我是abc线程
 7 我是main线程
 8 我是abc线程
 9 我是main线程
10 我是abc线程
11 我是main线程
12 我是abc线程
13 我是main线程
14 我是abc线程
15 我是main线程
16 我是abc线程
17 我是main线程
18 我是abc线程
19 我是main线程
20 我是abc线程
21 我是main线程
22 我是abc线程
23 我是abc线程
24 我是abc线程
25 我是abc线程
26 我是abc线程
27 我是abc线程
28 我是abc线程
29 我是abc线程
30 我是abc线程
31 我是abc线程
32 我是main线程
33 我是main线程
34 我是main线程
35 我是main线程
36 我是main线程
37 我是main线程
38 我是main线程
39 我是main线程
40 我是main线程

可以看到从第22行起就开始顺序执行了,因为i=10的时候就将该形成合并了。

  ③yield():暂停当前正在执行的线程对象,并执行其他线程。

  ④setPriority(): 更改线程的优先级。

    MIN_PRIORITY = 1
       NORM_PRIORITY = 5
           MAX_PRIORITY = 10

 1 package com.thread;
 2
 3
 4 /t.yield()暂停当前正在执行的线程对象,并执行其他线程。
 5
 6   MIN_PRIORITY 1
 7   NORM_PRIORITY 5
 8   MAX_PRIORITY 10
 9  /
10 public class TestYield {
11     public static void main(String[] args) {
12         Thread4 t1 = new Thread4(“t1”);
13         Thread4 t2 = new Thread4(“t2”);
14         t1.setPriority(Thread.MAX_PRIORITY);
15         t2.setPriority(Thread.MIN_PRIORITY);
16         System.out.println(t1.getPriority());
17         System.out.println(t2.getPriority());
18         t1.start();
19         t2.start();
20
21     }
22 }
23 class Thread4 extends Thread{
24     public Thread4(String s) {
25         super(s);
26     }
27     @Override
28     public void run() {
29         for (int i = 0; i < 1000; i++) {
30             System.out.println(“我是”+getName()+”线程”+i);
31             if(i%10 == 0){
32                 yield();
33             }
34         }
35     }
36 }

由于运行结果太长就没有贴上来了,运行该程序,可以看到t1和t2两个进程每次当i为10的倍数时都会让给其他线程执行。

  ⑤interrupt():中断某个线程,这种结束方式比较粗暴,如果t线程打开了某个资源还没来得及关闭也就是run方法还没有执行完就强制结束线程,会导致资源无法关闭

  要想结束进程最好的办法就是用sleep()函数的例子程序里那样,在线程类里面用以个boolean型变量来控制run()方法什么时候结束,run()方法一结束,该线程也就结束了。

  ⑥还有很多的方法就不一一列举了………

  当然,多线程难点不在这些,多线程的难点在于多线程之间的协调。关于多线程的协调待续……..

 

时间: 2024-08-22 18:58:49

java笔记五:多线程的使用的相关文章

Java笔记:多线程

一些概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程 是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在 Windows 系统中,一个运行的 exe 就是一个进程. 线程 是指进程中的一个执行流程,一个进程中可以运行多个线程.比如 java.exe 进程中可以运行很多线程.线程总是属于某个进程,进程中的多个线程共享进程的内存. 同时 执行是人的感觉,在线程之间实际上轮换执行. 多线程间堆空间共享,栈空间独立.堆存的是地址

java线程-java中的多线程?线程的并发问题

问题描述 java中的多线程?线程的并发问题 多线程具体代表java中程序的什么?它指的实际功能上的什么情况?详细求解 解决方案 多线程和进程的关系详解: 1.当我们运行QQ程序时,操作系统就会为这个程序创建一个QQ进程(QQ~PCB)并且分配CPU.内存等资源. 2.但这个进程中包含着:发送大型的线程.接受文件的线程.发送文字信息的线程.发送文字信息的线程等多个不同功能的线程. 因而我们才能一边发送文件,一边发送文字信息同时操作.这些线程都共享着QQ进程中的CPU.内存等资源. 总结:所以说进

kvm虚拟化学习笔记(五)之windows虚拟机性能调整

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://koumm.blog.51cto.com/703525/1290682 KVM虚拟化学习笔记系列文章列表 ---------------------------------------- kvm虚拟化学习笔记(一)之kvm虚拟化环境安装http://koumm.blog.51cto.com/703525/1288795 kvm虚拟化学习笔记(二)之linuxkvm虚拟机安装htt

浅谈java中异步多线程超时导致的服务异常_java

在项目中为了提高大并发量时的性能稳定性,经常会使用到线程池来做多线程异步操作,多线程有2种,一种是实现runnable接口,这种没有返回值,一种是实现Callable接口,这种有返回值. 当其中一个线程超时的时候,理论上应该不 影响其他线程的执行结果,但是在项目中出现的问题表明一个线程阻塞,其他线程返回的接口都为空.其实是个很简单的问题,但是由于第一次碰到,还是想了一些时间的.很简单,就是因为阻塞的那个线 程没有释放,并发量一大,线程池数量就满了,所以其他线程都处于等待状态. 附上一段自己写的调

关于JAVA四舍六入五成双不同JDK版本结果不一致的问题

问题描述 关于JAVA四舍六入五成双不同JDK版本结果不一致的问题 import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.NumberFormat; public class Utils { public static String getStrFromDb(Double db,Integer len){ String st="#0."; if(len==null || len==

mongodb-Mongodb在java中,多线程update时报错,请问是哪里出现的问题?

问题描述 Mongodb在java中,多线程update时报错,请问是哪里出现的问题? public class LocationPressureTest { private Todo todo; private int number; static Mongo mg = new Mongo("localhost", 27017); static DB db = mg.getDB("location_pressure_test_db"); static DBColl

控制-关于java的一个多线程问题,为什么输出的不是一次tom一次李四,是不是在输入判断0,1那里有问题?

问题描述 关于java的一个多线程问题,为什么输出的不是一次tom一次李四,是不是在输入判断0,1那里有问题? class Producer//这个是单生产线,单消费问题,一个单生产线有多条路径的问题(最后的效果的输入输出线程轮流执行) { public static void main(String[] args) { //创建资源 Resource res=new Resource(); //创建线程 input in=new input(res); output out=new outpu

java关于socket 多线程的问题

问题描述 java关于socket 多线程的问题 现在是指定一个时间,应用启动就开始定时扫描,隔一分钟扫描一次,到了指定的时间我就需要去Ping两千多台电脑,用多线程处理,每个线程负责50个.我该怎么处理?各位大神们,先说说思路再给我写点简单的代码啊.救急啊,我第一次搞这些东西完全不会额. 解决方案 public class Tdd { private static ScheduledThreadPoolExecutor es = new ScheduledThreadPoolExecutor(

方法-java怎么用多线程并发运行for?

问题描述 java怎么用多线程并发运行for? 如果把下面的改成十个线程并发运行不同的for语句,,就我最下面写好的那个方法,参数用定义好的数组里面的十个int变量,请问要怎么写? public static void main(String[] args) { for(Thread t:getThreads()){ t.start(); } } public static Thread[] getThreads(){ Thread[] thread = new Thread[10]; for(