java线程笔记(一)

线程和进程的基本概念

进程和线程是动态的概念。

        进程是 “执行中的程序“,是一个动词,而程序是一个名词,进程运行中程序的”代码“,而且还有自己的计数器,寄存器,它会向系统申请系统资源。

        线程是进程中的一个控制流。一个程序可能可能包含多个任务并发运行,而线程就是指一个任务重头到尾的执行流。

        说的在简单点,线程是执行中的任务,一个程序包含多个任务。

 

多线程

       单处理器中,为提高处理器的使用率(最终目标),使得程序在进行IO输入出等不需要处理器时,也能够让处理器在运转,引进多线程处理机制。多线程可以使得程序运行的更快,执行效率更高,交互性更强,这是不言而喻的!

 

创建任务和线程

        一个任务是一个对象,所以为创建一个任务,必须定义一个类,定义一个任务类,为了说明这是一个任务类,它需要实现Runnable接口,这个接口只包含一个run方法。

当我们定义好任务类taskClass之后,就可以用它的构造方法创建一个任务啦:TaskClass  task = new TaskClass(.....);

        我们创建的任务只能在线程中运行,Thread类中包含了创建线程以及控制线程的众多方法。使用下面的语句创建任务线程:Thread  thread  = new Thread(task);

        然后调用start()方法告诉java虚拟机该线程准备运行:thread.start();之后java虚拟机通过调用任务的run()方法执行任务。

 

事例代码:

public class TaskThreadDemo{
	public static void main(String[] args)
	{
		//创建任务   并且需要为任务 创建 任务类,使用该类的构造方法创建任务
		PrintChar printA = new PrintChar(‘a‘,100);
		PrintChar printB = new PrintChar(‘b‘,100);
		PrintNum print100 = new PrintNum(100);

		//为任务创建线程
		Thread thread1 = new Thread(printA);
		Thread thread2 = new Thread(printB);
		Thread thread3= new Thread(print100);

		//告诉虚拟机器线程开始运行
		thread1.start();
		thread2.start();
		thread3.start();
	}
}

class PrintChar implements Runnable
{
	private char  charToPrint;
	private int items;

	public PrintChar(char c,int t)
	{
		charToPrint = c;
		items = t;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<items;i++)
		{
			System.out.print(charToPrint);
		}
	}
}

class PrintNum implements Runnable
{
	private int lastNumb;
	public PrintNum(int n)
	{
		lastNumb = n;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i= 1;i<100;i++)
		{
			System.out.print(" "+lastNumb);
		}
	}

}

 

 

一个好玩的闪烁文本框,直接用线程,不用main方法

import javax.swing.JApplet;
import javax.swing.JLabel;
public class FlashingText extends JApplet implements Runnable {
	private static final long serialVersionUID = 1L;
	private JLabel jlbText = new JLabel("Welcome",JLabel.CENTER);

	public FlashingText()
	{
		add(jlbText);
		new Thread(this).start();
	}

	public void run()
	{
		try {
			while(true)
			{
				if(jlbText.getText()==null)
					jlbText.setText("Welcome");
				else
					jlbText.setText(null);
				Thread.sleep(200);
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

 

 

Thread类

        Thread类实现了Runnable接口,它包含为任务而创建线程的构造方法,以及控制方法,下图就是Thread类常见的控制线程的方法:

          因为Thread类实现了Runnable接口,所以可以定义一个Thread的扩展类,里面实现run方法,这样也可以创建一个线程类,但并不是很推荐这种方法,因为它将创建任务和运行任务的机制混在了一起,将任务从线程中分离出来比较好,即尽量使用Runnable接口创建线程,这样得到的线程更加灵活,避免了java单继承带来的局限性。

 

线程池

           线程池是管理并发执行任个数的理想方法,java提供Executor接口来执行线程池中的任务,提供ExecutorService接口来管理和控制任务。为了创建Executor接口实例,我们可以用Executors类,Executors类提供了创建Executor接口对象的静态方法,下图描述了上面的上面所说的关系。

 

       线程池中的shutdown()方法一般都是放在main方法的后面部分,当所以的线程都添加到线程池中,即便有线程没有执行完毕,也可能会关闭线程池,未执行完的线程继续执行,所以main方法可能比子线程先结束。

利用isTerminated()进行线程池中所有线程运行时间的统计

       倘若希望主线程在子线程全部做完之后在执行,可以考虑让所以的子线程用jion方法,但这可能导致所有子线程变成串行,不是很好的办法,当然我们也可以多线程的辅助类CountDownLatch,这是一个与计时器有点类似功能的类。这次在看书学习的时候,发现了一个更好的办法,就是在shutdown()方法后加上一句while(!executor.isTerminated()){},这是一个不错的方法(不过我把shoudown()方法放在该while语句后面,就会陷入死循环,应该是要先关闭线程池,在判断线程池中的线程是否全部终止,因为也有可能在while语句后面在添加新的子线程)。

       isTerminated()方法:如果线程池中所以线程都已完成并终止,则返回true.

       可以使用CountDownLatch 和上面的方法对程序运行计时统计,不过我记得CountDownLatch类是需要指定线程的个数。

事例代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorDemo {
	public static void main(String[] args){
		long start = System.currentTimeMillis();
		System.out.println("当前时间"+"  "+start);
		ExecutorService executor = Executors.newFixedThreadPool(4);

		executor.execute(new PrintChar(‘a‘,100));
		executor.execute(new PrintChar(‘b‘,100));
		executor.execute(new PrintChar(‘c‘,100));
	    executor.execute(new PrintNum(100));

	    executor.shutdown();
		while(!executor.isTerminated()){
			//System.out.print("-");
		};

		long end = System.currentTimeMillis();
		System.out.println("\n当前时间"+"  "+end);
		System.out.println("\n用时"+"  "+(end-start)+"毫秒");
	}
}
 
运行截图
截图1      截图2

不过不知道运行太快的原因,还是啥别的原因,这个方法好像还是不灵, 会出现截图2的情况,网上很少关于isTerminated()方法的介绍,如有大神知道原因,还请告知小弟。

 

这篇博客是自己在学习《java语言程序设计进阶篇》时所在笔记,代码出自书上,最后那个记时的加了计时部分。大三开学在即,希望现在来学java还来得及。

时间: 2024-10-25 07:07:28

java线程笔记(一)的相关文章

Java 线程第三版 第四章 Thread Notification 读书笔记

一.等待与通知 public final void wait() throws InterruptedException 等待条件的发生. public final void wait(long timeout) throws InterruptedException 等待条件的发生.如果通知没有在timeout指定的时间内发生,它还是会返回. public final void wait(long timeout, int nanos) throws InterruptedException

[Java基础] Java线程复习笔记

先说说线程和进程,现代操作系统几乎无一例外地采用进程的概念,进程之间基本上可以认为是相互独立的,共享的资源非常少.线程可以认为是轻量级的进 程,充分地利用线程可以使得同一个进程中执行多种任务.Java是第一个在语言层面就支持线程操作的主流编程语言.和进程类似,线程也是各自独立的,有自 己的栈,自己的局部变量,自己的程序执行并行路径,但线程的独立性又没有进程那么强,它们共享内存,文件资源,以及其他进程层面的状态等.同一个进程内的 多个线程共享同样的内存空间,这也就意味着这些线程可以访问同样的变量和

java学习笔记14--多线程编程基础1

本文地址:http://www.cnblogs.com/archimedes/p/java-study-note14.html,转载请注明源地址. 多线程编程基础 多进程 一个独立程序的每一次运行称为一个进程,例如:用字处理软件编辑文稿时,同时打开mp3播放程序听音乐,这两个独立的程序在同时运行,称为两个进程 进程要占用相当一部分处理器时间和内存资源 进程具有独立的内存空间 通信很不方便,编程模型比较复杂 多线程 一个程序中多段代码同时并发执行,称为多线程,线程比进程开销小,协作和数据交换容易

Java 线程第三版 第六章 高级同步议题 读书笔记

多线程数据同步错误比较难检测,因为通常是与事件的特定发生顺序有关. 一.同步术语 Barrier(屏障) barrier是多个Thread的集合点:所有的Thread都应该到齐在这个barrier之后才能允许它们继续下去. Condition variable(条件变量) 实际上不是变量,而是与某个lock有关联的变量. Event variable(事件变量) 条件变量的另一个名称. Critical section(临界区) 临界区是synchronized方法或者block. Lock(锁

Java 线程第三版 第八章 Thread与Collection Class 读书笔记

JDK1.2引入最有争议性的改变是将集合类默认为不是Thread安全性的. 一.Collection Class的概述 1. 具有Threadsafe 的Collection Class: java.util.Vector(List) 列表集合,通过索引操作. java.util.Stack(List) 继承自Vector,提供LIFO的顺序操作push进入,pop出元素. java.util.Hashtable(Map) 一个简单.无序的key与value的映射. java.util.conc

Java 线程第三版 第一章Thread导论、 第二章Thread的创建与管理读书笔记

第一章 Thread导论 为何要用Thread ? 非阻塞I/O I/O多路技术 轮询(polling) 信号 警告(Alarm)和定时器(Timer) 独立的任务(Task) 并行算法 第二章 Thread的创建与管理 一.什么是Thread ? Thread是所在主机执行的应用程序任务(task). 只有一个线程的例子: public class Factorial { public static void main(String[] args) { int n = 5; System.ou

Java 线程第三版 第三章数据同步 读书笔记

多线程间共享数据问题 一.Synchronized关键字 atomic一词与"原子"无关,它曾经被认为是物质的最小的单元,不能再被拆解成更小的部分. 当一个方法被声明成synchronized,要执行此方法的thread必须先取得一个token,我们将它称为锁.一旦该方法取得(或者说是获得)锁,它将运行此方法然后释放掉(或者返回)此锁.不管方法时怎样返回的(包括通过异常)该锁会被释放. 二.Volatile关键字 如果变量被标示为volatile,每次使用该变量时都必须从主寄存器中读出

Java 线程第三版 第五章 极简同步技巧 读书笔记

一.能避免同步吗? 取得锁会因为以下原因导致成本很高: 取得由竞争的锁需要在虚拟机的层面上运行更多的程序代码. 要取得有竞争锁的线程总是必须等到锁被释放后. 1. 寄存器的效应 计算机有一定数量的主寄存器用来存储与程序有关的数据. 从逻辑上的观点来看,每个Thread都有自己的一组寄存器.当操作系统将某个Thread分配给CPU时,它会把该Thread特有的信息加载到CPU的寄存器中.在分配不同的Thread给CPU之前,它会将寄存器的信息存下来.所以Thread间绝不会共享保存在寄存器的数据.

Java 线程第三版 第九章 Thread调度 读书笔记

一.Thread调度的概述 import java.util.*; import java.text.*; public class Task implements Runnable { long n; String id; private long fib(long n) { if (n == 0) return 0L; if (n == 1) return 1L; return fib(n - 1) + fib(n - 2); } public Task(long n, String id)