传统线程
来源:互联网 发布:淘宝小号批量死的原因 编辑:程序博客网 时间:2024/04/29 14:26
在计算机系统中有多个并发执行的程序,"程序"这个静态的概念已经不能描述程序动态变化的过程,所以引入了"进程".进程是程序的一次执行,进程由3大部分组成,程序、数据、进程控制块,传统的进程有两个基本的属性,可拥有资源的独立单位,可独立调度和分配的基本单位。由于频繁创建进程等一系列操作,时空开销很大,这就限制了并发程序的提高,所以就引入了线程,将进程中的两个基本属性分开,线程作为独立调度和分配的基本单位,进程作为独立分配资源的单位。线程和进程很相似,线程被称为轻量进程,进程被称为重量进程。简单的说线程就是一条执行路径,多条执行路径也就是多线程了,值得注意的是多线程并不能提高程序的运行效率,反而会降低程序的运行效率,因为cpu只有一个,按照时间片轮转的调度算法可以得知,只不过cpu的运行速度对于人类来说很快感觉不到便会认为程序是同时执行的。所谓同时执行 其实是cpu逐一来为每一个进程服务。我们常常可以看到的多线程下载又是怎么回事呢?那是因为抢占了服务器的带宽了。
线程是系统的资源,java对其进行了描述,java描述事物也就是用类啦。提供了一系列有关操作线程的方法,
这个类就是:
java.lang
类 Thread
java.lang.Object java.lang.Thread
- 所有已实现的接口:
- Runnable
public class Thread
- extends Object
- implements Runnable
- 1.线程的创建。
- new Thread().start();//开辟了一条新的执行路径。
- 线程要运行的代码是放在run(){}方法中的。这个没有为什么。
- new Thread().start();//运行是没有反应。查看源码可以知道:
- public void run() {
if (target != null) {
target.run();
} - target是:private Runnable target;
- 1).创建线程的方式一:
- 继承Thread类覆盖run方法。
- 2).将run()方法的代码封装到一个Runnable接口中。通过构造方法传递给线程。
- new Thread(new Runnable(){
- run....
- }).start();
继承Thread创建线程是将线程和线程的任务绑定在一起,耦合度高,而通过Runnable接口将线程和线程的任务分开,更符合面向对 象的思想,实现了低耦合高内聚的设计思想。
3.线程的5种状态,见下图:
线程的创建方式demo
<span style="font-size:18px;">public static void main(String[] args) {new Thread(new Runnable(){@Overridepublic void run() {while(true){System.out.println(Thread.currentThread().getName());}}}).start();new Thread(){public void run() {while(true){System.out.println(Thread.currentThread().getName());}};}.start();//运行那个run方法???//创建的是Thread的匿名子类对象并且覆盖了run方法,故运行的是子类的run方法。new Thread(new Runnable(){@Overridepublic void run() {while(true){System.out.println(Thread.currentThread().getName()+"runnable");}}}){public void run() {while(true){System.out.println(Thread.currentThread().getName()+"Thread sub");}};}.start();new Thread(){@Overridepublic void run() {};}.start();}</span>
3.线程的同步互斥与通信。
1)同步互斥:
由于cpu是随机切换的, 在多线程环境中,各个线程可以共享各类资源,但有一些资源一次只能提供给一个线程使用,称为这些资源 称为临界资源。例如卖票。有100张票,分4个窗口来卖,每一个窗口相当于一个线程。多线程访问共享数据会出现安全问题,需要 特别”处理“.
<span style="font-size:18px;">package com.hb;public class TraditionalSynchronizedTest {public static void main(String[] args) { new TraditionalSynchronizedTest().init(); }public void init(){final Outputer output=new Outputer();new Thread(new Runnable(){@Overridepublic void run() { while(true){ output.output("hbbb"); }}}).start();new Thread(new Runnable(){@Overridepublic void run() { while(true){ output.output("china"); }}}).start();}class Outputer{private String xxx="";public void output(String name){int len =name.length();synchronized (xxx) {//锁是xxxfor(int i =0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}}public synchronized void output2(String name){//锁是thisint len =name.length();for(int i =0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}}public static synchronized void output3(String name){//锁是当前字节码对象int len =name.length();for(int i =0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}}</span>
2) 线程间的通信:
多个线程可以并发执行,每一个线程都以各自独立、不可预知的速度向前推进。但是需要在某个点上相互协调合作,例如:经典问 题生产者和消费者,生产者生产一个产品,消费者消费一个产品,由于cpu...,如果生产者没有生产出产品,消费者就必须等待 (wait),消费者没有消费产品,生产都也必须等待。这就涉及到了线程间的通信,方法有,wait()、notify()、notifyAll()。这些方法都是 定义在Object类中的,为什么?因为锁可以是任意对象,而玩线程间的通信时必须标明所属的锁,锁相当于定义了一个范围,例如: this.notify(),是唤醒this这个锁上的任意一个线程,没有锁没得玩啊,所以这些方法也就被定义在Object类中了。
<span style="font-size:18px;">package com.hb;public class TraditionalThreadCommunication {/** * * 面试题: * 子线程循环10次,主线程循环20次,接着又是子线程循环10次,主线程循环20次,如此重复50次。 */public static void main(String[] args) {final Business b=new Business(); new Thread(new Runnable(){@Overridepublic void run() { for(int i =1;i<=50;i++){b.sub1(i); }}}).start();for(int i=1;i<=50;i++){b.main(i);}}}//将需要同步的代码提取出来单独存在,这样可以提高代码的扩展性等。class Business{private boolean flag =true;public synchronized void sub1(int i){//如果不是我,那就等待,由于线程存在伪唤醒的情况,所以给整个while(),用if也是可以的,不过不建议。 while(!flag){ try {this.wait();} catch (InterruptedException e) {e.printStackTrace();} }for(int j =1;j<=10;j++){System.out.println("sub thread sequence of "+j+" ,loop of "+i);}flag=false;this.notify();}public synchronized void main(int i ){ while(flag){ try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}for(int j =1;j<=20;j++){System.out.println("main thread sequence of "+j+" ,loop of "+i);}flag=true;this.notify();}}}</span>
4.传统定时器:
故名思义....
<span style="font-size:18px;">package com.hb;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class TraditionalTimerTest {/** * @param args */public static void main(String[] args) {// 传统定时器// Timer(),是定时器。// schedule(TimerTask ,x)调度// TimerTask是任务// x ,时间,什么时候bombing?/*new Timer().schedule(new TimerTask() {@Overridepublic void run() { System.out.println("bombing!");}}, 500);//固定频率炸,也就是连环炸。 new Timer().scheduleAtFixedRate( new TimerTask() {@Overridepublic void run() {System.out.println("bombing!");}}, 1000, 2000);*/ //2秒搞一下,4秒搞一下,再2秒搞一下,如此循环class MyTimerTask extends TimerTask{ int count =0;@Overridepublic void run() { System.out.println("bombing!"); count=(count+1)%2; new Timer().schedule(new MyTimerTask(), 2000+2000*count);}}new Timer().schedule(new MyTimerTask(), 2000);while(true){System.out.println(new Date().getSeconds());try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}</span>
- 传统线程
- 传统线程操作
- JAVA传统线程技术
- 传统线程技术回顾
- 传统线程技术回顾
- 传统线程机制
- Java 传统线程技术
- 传统线程调用
- 传统线程(一)
- java传统线程介绍
- 传统线程通信技术
- 传统线程技术回顾
- 传统线程的创建
- JUC线程-传统线程回顾
- Java线程之传统线程
- 传统线程同步通讯技术
- 传统线程同步通信技术
- 传统线程互斥技术
- Javah 使用时报错:找不到类
- NodeJS、NPM安装配置步骤(windows版本)
- 随记
- linux2.6.32.2 mini2440平台移植-- UDA1341 音频驱动移植
- dos命令for用法详解
- 传统线程
- 栈Stack和队列Queue
- Eclipse自动生成作者、日期注释等功能设置
- android的消息处理机制(图+源码分析)——Looper,Handler,Message
- netlink_kernel_create
- 李浚慶
- TCP中RTT和RTO的计算方法
- 约瑟夫环--不用链表的一般c程序
- My Site Clean Up Job介绍----自定义开发