sleep和wait的区别:

1. sleep是Thread的方法, wait是object的方法

2.  sleep占着CPU睡觉, wait等待CPU,不占用CPU

线程是一个程序内部的顺序控制流

线程和进程的区别:

1. 每个进程都有独立的代码和数据空间, 进程间的切换会有很大的开销.

2. 线程可以看成是轻量级的进程, 同一类线程共享代码和数据空间, 每个线程有独立的运行栈和程序计数器PC, 线程切换的开销小.

3. 多进行, 在操作系统中能同时运行多个任务(程序)

4. 多线程:在同一个程序可以有多个顺序刘同时执行.

通过创建Thread的实例来创建新的线程

每个线程都通过特定Thread对象对应的run方法来完成操作, 方法run称为线程体

通过调用Thread类的start方法启动一个线程

run是方法调用,start是开启一个线程

以下程序只有一个线程 main, 主线程

public class {
public static void main(String[] args) {
m1();
} public static void m1() {
m2();
m3();
} public static void m2() {}
public static void m3() {}
}

进程: 一个class文件, 一个exe文件, 是个静态的概念.进程的执行指的是一个主线程开始执行, 即main开始.

所以机器里我们运行的都是线程.

建议使用以下接口的方式:

public class TestThread1 {
public static void main(String args[]) {
Runner1 r = new Runner1();
Thread t = new Thread(r);
t.start();
for(int i=0; i<100; i++) {
System.out.println("Main Thread:------" + i);
}
}
} class Runner1 implements Runnable {
public void run() {
for(int i=0; i<100; i++) {
System.out.println("Runner1 :" + i);
}
}
}

还有一种方法,继承Thread,不建议使用:

public class TestThread1 {
public static void main(String args[]) {
Runner1 r = new Runner1();
r.start();
for(int i=0; i<100; i++) {
System.out.println("Main Thread:------" + i);
}
}
} class Runner1 extends Thread {
public void run() {
for(int i=0; i<100; i++) {
System.out.println("Runner1 :" + i);
}
}
}

  

线程状态转换:

创建-->start-->就绪--> 运行-->终止  运行-->阻塞状态-->就绪 

线程控制的方法:

isAlive():  阻塞,运行, 就绪,

getPriority() 获得优先级

setPriority(): 设置优先级

Thread.sleep(): 将当前线程睡眠指定毫秒数

join(): 合并, 等改线程结束再恢复当前线程的运行

yield(): 让出CPU, 当前线程进去就绪状态等待调度

wait(): 当前线程进入wait pool

sleep方法: Thread类的静态方法:

import java.util.*;
public class TestInterrupt {
public static void main(String[] args) {
Runner r = new Runner();
Thread t = new Thread(r);
t.start();
try {Thread.sleep(10000);}
catch (InterruptedException e) {}
//t.interrupt(); //打断子线程,比较粗暴
r.flag=false; //替换上面的打断子线程的方式, 用这种方式, run方法里的return也可以注释掉了
}
} class Runner implements Runnable {
   boolean flag = true;
  public void run(){
while(flag){
System.out.println("==="+new Date()+"===");
try {
Thread.sleep(1000);
} catch (InterruptedException e) { //被打算后进入异常, return
return;
}
}
}
}

结果:每隔一秒显示一次:

===Fri Apr 08 10:53:44 CST 2016===
===Fri Apr 08 10:53:45 CST 2016===
===Fri Apr 08 10:53:46 CST 2016===
===Fri Apr 08 10:53:47 CST 2016===
===Fri Apr 08 10:53:48 CST 2016===
===Fri Apr 08 10:53:49 CST 2016===
===Fri Apr 08 10:53:50 CST 2016===
===Fri Apr 08 10:53:51 CST 2016===
===Fri Apr 08 10:53:52 CST 2016===
===Fri Apr 08 10:53:53 CST 2016===

  

join用法:相当于调用, 如果main里调用join, 那么会等join的线程执行完才能执行自己的线程:

public class TestJoin {
public static void main(String[] args) {
MyThread2 t1 = new MyThread2("abcde");
t1.start();
try {
t1.join();
} catch (InterruptedException e) {} for(int i=1;i<=10;i++){
System.out.println("i am main thread");
}
}
}
class MyThread2 extends Thread {
MyThread2(String s){
super(s);
} public void run(){
for(int i =1;i<=10;i++){
System.out.println("i am "+getName());
try {
sleep(1000);
} catch (InterruptedException e) {
return;
}
}
}
}

结果:

i am abcde
i am abcde
i am abcde
i am abcde
i am abcde
i am abcde
i am abcde
i am abcde
i am abcde
i am abcde
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread

  

yield方法: 让出CPU, 给其他线程执行的机会:

只要运行的线程 i 被10整除, 就让出给别的线程运行

public class TestYield {
public static void main(String[] args) {
MyThread3 t1 = new MyThread3("t1");
MyThread3 t2 = new MyThread3("t2");
t1.start(); t2.start();
}
}
class MyThread3 extends Thread {
MyThread3(String s){super(s);}
public void run(){
for(int i =1;i<=100;i++){
System.out.println(getName()+": "+i);
if(i%10==0){
yield();
}
}
}
}

  

线程的优先级:

public class TestPriority {
public static void main(String[] args) {
Thread t1 = new Thread(new T1());
Thread t2 = new Thread(new T2());
t1.setPriority(Thread.NORM_PRIORITY + 3);
t1.start();
t2.start();
}
} class T1 implements Runnable {
public void run() {
for(int i=0; i<100; i++) {
System.out.println("T1: " + i);
}
}
} class T2 implements Runnable {
public void run() {
for(int i=0; i<100; i++) {
System.out.println("------T2: " + i);
}
}
}
Thread.MIN_PRIORITY=1;

Thread.MAX_PRIORITY=10;

Thread.NORM_PRIORITY=5;

  

同一个线程对象可以定义两个Thread:

public class TestThread2 {
public static void main(String args[]) {
Runner2 r = new Runner2();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
} class Runner2 implements Runnable {
public void run() {
for(int i=0; i<30; i++) {
System.out.println("No. " + i);
}
}
}

被10整除就停顿2s:

public class TestThread3{
public static void main(String args[]) {
Runner3 r = new Runner3();
Thread t = new Thread(r);
t.start();
}
} class Runner3 implements Runnable {
public void run() {
for(int i=0; i<30; i++) {
if(i%10==0 && i!=0) {
try{
Thread.sleep(2000);
}catch(InterruptedException e){}
}
System.out.println("No. " + i);
}
}
}

如何恰当的结束线程, 用flag:

public class TestThread4 {
public static void main(String args[]){
Runner4 r = new Runner4();
Thread t = new Thread(r);
t.start();
for(int i=0;i<100000;i++){
if(i%10000==0 & i>0)
System.out.println("in thread main i=" + i);
}
System.out.println("Thread main is over");
r.shutDown();
//t.stop();
}
} class Runner4 implements Runnable {
private boolean flag=true; public void run() {
int i = 0;
while (flag==true) {
System.out.print(" " + i++);
}
} public void shutDown() {
flag = false;
}
}

isAlive:

public class TestThread6 {
public static void main(String args[]){
Thread t = new Runner6();
t.start();
for(int i=0; i<50; i++) {
System.out.println("MainThread: " + i);
}
}
} class Runner6 extends Thread {
public void run() {
System.out.println(Thread.currentThread().isAlive());
for(int i=0;i<50;i++) {
System.out.println("SubThread: " + i);
}
}
}

线程同步: synchronized:

执行方法的过程中当前对象被锁定, 这样对象控制一个过程, 别的线程不可打扰.

public class TestSync implements Runnable {
Timer timer = new Timer();
public static void main(String[] args) {
TestSync test = new TestSync();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
public void run(){
timer.add(Thread.currentThread().getName());
}
} class Timer{
private static int num = 0;
public synchronized void add(String name){ //执行方法的过程中锁定当前对象
//synchronized (this) { //方法不加同步的话, 可以用此方法体的方式锁定
num ++;
try {Thread.sleep(1);}
catch (InterruptedException e) {}
System.out.println(name+", 你是第"+num+"个使用timer的线程");
//}
}
}

结果:

不加synchronized的话, 就都显示2

t1, 你是第1个使用timer的线程
t2, 你是第2个使用timer的线程

  

用synchronize的时候会出现死锁的现象,比如线程A执行过程中,锁定某一个对象1.   另一个线程B锁定另一个对象2, 线程A 需要继续锁定对象2, 线程B需要锁定对象1, 就会发生死锁.

public class TestDeadLock implements Runnable {
public int flag = 1;
static Object o1 = new Object(), o2 = new Object();
public void run() {
System.out.println("flag=" + flag);
if(flag == 1) {
synchronized(o1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized(o2) {
System.out.println("1");
}
}
}
if(flag == 0) {
synchronized(o2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized(o1) {
System.out.println("0");
}
}
}
} public static void main(String[] args) {
TestDeadLock td1 = new TestDeadLock();
TestDeadLock td2 = new TestDeadLock();
td1.flag = 1;
td2.flag = 0;
Thread t1 = new Thread(td1);
Thread t2 = new Thread(td2);
t1.start();
t2.start(); }
}

结果: 线程不动了:

flag=1
flag=0

线程锁死后, 别的方法还可以访问

public class TT implements Runnable {
int b = 100; public synchronized void m1() throws Exception{
b = 1000;
Thread.sleep(5000);
System.out.println("b = " + b);
} public void m2() {
System.out.println(b);
} public void run() {
try {
m1();
} catch(Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);
t.start();
Thread.sleep(1000);
tt.m2();
}
}

结果:

1000
b = 1000

上例子改一下:

public class TT implements Runnable {
int b = 100; public synchronized void m1() throws Exception{
b = 1000;
Thread.sleep(5000);
System.out.println("b = " + b);
} public void m2() throws Exception {
Thread.sleep(2500);
b = 2000;
} public void run() {
try {
m1();
} catch(Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);
t.start(); tt.m2();
System.out.println(tt.b);
}
}

结果:

2000
b = 2000

再改一下:

1. 先执行m2, 执行完后

2. m1 执行 b=1000;

3. 主线程执行 输出b

4. m1 执行 输出b=1000;

public class TT implements Runnable {
int b = 100; public synchronized void m1() throws Exception{
b = 1000;
Thread.sleep(5000);
System.out.println("b = " + b);
} public synchronized void m2() throws Exception {
Thread.sleep(2500);
b = 2000;
} public void run() {
try {
m1();
} catch(Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);
t.start();
tt.m2();
System.out.println(tt.b);
}
}

结果:

1000
b = 1000

  

wait必须和synchronized同时出现, 不能单独使用wait, wait是object类的方法.

wait的时候锁不归我所有, sleep的时候, 还抱着锁.

wait后需要notify叫醒, 也是object类的方法

public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
new Thread(p).start();
new Thread(c).start();
}
} class WoTou {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
} class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6]; public synchronized void push(WoTou wt) {
while(index == arrWT.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
arrWT[index] = wt;
index ++;
} public synchronized WoTou pop() {
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
index--;
return arrWT[index];
}
} class Producer implements Runnable {
SyncStack ss = null;
Producer(SyncStack ss) {
this.ss = ss;
} public void run() {
for(int i=0; i<10; i++) {
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("生产了:" + wt);
try {
Thread.sleep((int)(Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} class Consumer implements Runnable {
SyncStack ss = null;
Consumer(SyncStack ss) {
this.ss = ss;
} public void run() {
for(int i=0; i<10; i++) {
WoTou wt = ss.pop();
System.out.println("消费了: " + wt);
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

  

  

  

  

  

JAVA基础--线程的更多相关文章

  1. Java基础-线程安全问题汇总

    Java基础-线程安全问题汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.内存泄漏和内存溢出(out of memory)的区别 1>.什么是内存溢出 答:内存溢出指 ...

  2. Java基础-线程操作共享数据的安全问题

    Java基础-线程操作共享数据的安全问题 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.引发线程安全问题 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运 ...

  3. Java基础——线程总结

    Java基础--线程总结 一.线程是什么? 线程:一个程序里不同的运行路径. 二.怎样创建线程? 两种方法创建线程: 第一种 (1)定义详细功能类实现Runnable接口,能够多次调用而实现数据共享 ...

  4. 《Java基础——线程类》

    Java基础--线程类       一.线程的创建之Thread类: 规则: 通过声明一个新类作为子类继承 Thread 类,并复写 run() 方法,就可以启动新线程并执行自己定义的 run()方法 ...

  5. JAVA基础—线程池

    推荐文章java多线程基础 线程池概述 为什么要使用线程池 1.服务器创建和销毁工作线程的开销很大 2.如果频繁的创建和销毁线程会导致频繁的切换线程,因为一个线程被销毁后,必然要把CPU转让给另一个已 ...

  6. java基础—线程(一)

    一.线程的基本概念

  7. java基础—线程(二)

    一.线程的优先级别

  8. Java基础--线程创建方式

    线程的创建主要有两种形式,通过继承Thread或者实现Runnable接口,本质上没有太大区别. /** * @date: 2019/7/16 **/ public class ThreadOne i ...

  9. Java基础-线程与并发1

    线程与并发 Thread 基本概念 程序: 一组计算机能识别和执行的指令 ,是静态的代码. 进程: 程序的一次运行活动, 运行中的程序 . 线程: 进程的组成部分,它代表了一条顺序的执行流. 进程线程 ...

  10. 面试题-Java基础-线程部分

    1.进程和线程的区别是什么? 进程是执行着的应用程序,而线程是进程内部的一个执行序列.一个进程可以有多个线程.线程又叫做轻量级进程. 2.创建线程有几种不同的方式?你喜欢哪一种?为什么? 有三种方式可 ...

随机推荐

  1. Spring security 获取当前用户

    spring security中当前用户信息 1:如果在jsp页面中获取可以使用spring security的标签库 在页面中引入标签   1 <%@ taglib prefix=" ...

  2. MVC4相关Razor语法以及Form表单(转载)

    Razor的布局(Layout) 默认建的工程都自带的了一个_ViewStart.cshtml文件,文件里面的代码如下: @{ Layout = "~/Views/Shared/_Layou ...

  3. 最大边和最小边之差最小的生成树 UVA 1394

    题目大意:给你n个点的图,求苗条度(最大边减最小编)尽量小的生成树 思路:sort以后暴力枚举区间即可 //看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #inclu ...

  4. sql数据库删除表的外键约束(INSERT 语句与 FOREIGN KEY 约束"XXX"冲突。该冲突发生于数据库"XXX",表"XXX", column 'XXX)

    使用如下SQL语句查询出表中外键约束名称: 1 select name 2 from sys.foreign_key_columns f join sys.objects o on f.constra ...

  5. WampServer 下载以及安装问题

    WampServer 3.0 下载: http://dl.pconline.com.cn/download/52877-1.html 碰到的问题DDL无法添加,解决方法: http://jingyan ...

  6. redis采用序列化方案存对象

    前几天被问到这样一个问题,redis怎么存对象,平时也没怎么注意,只知道redis存字符之类的,不过就是根据键存取值,不过对象的话还是不同的 首先来了解一下为什么要实现序列化 为什么要实现序列化接口 ...

  7. php 数据库并发处理

    在并行系统中并发问题永远不可忽视.尽管PHP语言原生没有提供多线程机制,那并不意味着所有的操作都是线程安全的.尤其是在操作诸如订单.支付等业务系统中,更需要注意操作数据库的并发问题. 接下来我通过一个 ...

  8. jquery 简单的栏目切换

    <style> ul{ list-style:none; padding:0px; margin:0px;} #nav_box{ width:502px; height:402px; ov ...

  9. pycharm快捷键、常用设置、配置管理

    http://blog.csdn.net/pipisorry/article/details/39909057 pycharm学习技巧 Learning tips /pythoncharm/help/ ...

  10. java 集合大家族

    在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的ArrayList. ...