1、多线程的基本概念:
package com.geeklicreed.j2se;
/*
* 分析以下程序有几个线程?
* 以下程序只有一个线程,就是主线程
* main,m1,m2,m3这四个方法都在同一个栈空间中
* 没有启动其他任何线程。
*/
public class ThreadTest {
public static void main(String[] args){
m1();
}
public static void m1(){
m2();
}
public static void m2(){
m3();
}
public static void m3(){
System.out.println("m3...");
}
}
3、线程的定义、创建和启动:(第一种方式)
@Override
public void run(){
if(target != null){
target.run(); // targer引用为Runnable类型
}
}
示例代码:(需要注意的是,有了多线程之后,main方法结束只是主线程中没有方法栈帧,但是其他线程或者其他栈中还有栈帧,所以main方法结束,程序可能还在运行。)
package com.geeklicreed.j2se;
public class ThreadTest {
public static void main(String[] args){
//创建线程
Thread t = new Processor();
//启动
t.start(); // 这段代码执行瞬间结束,告诉JVM再分配一个新的栈给t线程
//这段代码在主线程中运行
for(int i = 0; i < 10; i++){
System.out.println("main -->" + i);
}
}
}
//定义一个线程
class Processor extends Thread{
//重写run方法
public void run(){
for(int i = 0; i < 100; i++){
System.out.println("run -->" + i);
}
}
}
构造器Thread(Runnable target)方法可以传递Runnable类型的对象创建线程:
示例代码:
package com.geeklicreed.j2se;
public class ThreadTest {
public static void main(String[] args){
//创建线程
Thread t = new Thread(new Processor());
//启动
t.start();
}
}
//这种方式是推荐的,因为一个类实现接口以外保留了类的继承
class Processor implements Runnable{
@Override
public void run() {
for(int i = 0; i < 10; i++){
System.out.println("run -->" + i);
}
}
}
5、关于线程的生命周期:(状态图)
package com.geeklicreed.j2se;
public class ThreadTest {
public static void main(String[] args) throws Exception{
//创建线程
Thread t = new Processor();
t.setName("t");
//启动线程
t.start();
//休眠
t.sleep(5000); //等同于Thread.sleep(5000);阻塞的还是当前线程,和t线程无关
System.out.println("HelloWorld");
}
}
class Processor extends Thread{
@Override
public void run() {
for(int i = 0; i < 200; i++){
System.out.println(Thread.currentThread().getName() + " --> " + i);
}
}
}
package com.geeklicreed.j2se;
/*
* 某线程正在休眠,如何打断它的睡眠
*/
public class ThreadTest {
public static void main(String[] args) throws Exception{
//需求:启动线程,5秒后打断线程的休眠
Thread t = new Thread(new Processor());
//起名
t.setName("t");
//启动
t.start();
//5秒之后
Thread.sleep(5000);
//打断t的睡眠
t.interrupt();
/*
输出结果为:
t-->0
t-->1
t-->2
t-->3
t-->4
t-->5
t-->6
t-->7
t-->8
t-->9
*/
}
}
class Processor implements Runnable{
@Override
public void run() {
try {
Thread.sleep(10000000000000L);
System.out.println("HelloWorld");
} catch (Exception e) {
}
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
}
8、yield方法和线程合并:
package com.geeklicreed.j2se;
/*
* 线程的合并
*/
public class ThreadTest {
public static void main(String[] args) throws Exception{
Thread t = new Thread(new Processor());
t.setName("t");
t.start();
//合并线程
t.join(); //t和主线程合并,单线程的程序
//主线程
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
/*
输出结果为:
t-->0
t-->1
t-->2
t-->3
t-->4
main-->0
main-->1
main-->2
main-->3
main-->4
main-->5
main-->6
main-->7
main-->8
main-->9
*/
}
}
class Processor implements Runnable{
@Override
public void run() {
for(int i = 0; i < 5; i++){
try {
Thread.sleep(1000);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
}
9、线程的同步:
线程同步中的锁机制:(示例代码)
package com.geeklicreed.j2se;
/*
* 以下程序使用线程同步机制保证数据的安全
*/
public class ThreadTest {
public static void main(String[] args) throws Exception {
//创建一个公共的账户
Account act = new Account("actno-001", 5000.0);
//创建线程对同一个账户取款
Thread t1 = new Thread(new Processor(act));
Thread t2 = new Thread(new Processor(act));
t1.start();
t2.start();
/*
输出结果为:
取款1000.0成功,余额:4000.0
取款1000.0成功,余额:3000.0
*/
}
}
// 取款线程
class Processor implements Runnable {
// 账户
Account act;
public Processor(Account act) {
super();
this.act = act;
}
@Override
public void run() {
act.withdraw(1000.0);
System.out.println("取款1000.0成功,余额:" + act.getBalance());
}
}
// 账户
class Account {
private String actno;
private double balance;
public Account(String actno, double balance) {
super();
this.actno = actno;
this.balance = balance;
}
public Account() {
// TODO Auto-generated constructor stub
}
public String getActno() {
return actno;
}
public void setActno(String actno) {
this.actno = actno;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
// 对外提供一个取款的方法
public void withdraw(double money) { // 对当前账户进行取款操作
// 把需要同步的代码,放到同步语句块中
synchronized (this) {
double after = balance - money;
// 延迟
try {
Thread.sleep(1000);
} catch (Exception e) {
}
// 更新
this.setBalance(after);
}
}
}
package com.geeklicreed.j2se;
public class ThreadTest {
public static void main(String[] args) throws Exception {
MyClass mc = new MyClass();
Processor p = new Processor(mc);
Thread t1 = new Thread(p);
t1.setName("t1");
Thread t2 = new Thread(p);
t2.setName("t2");
//启动线程
t1.start();
//延迟(保证t1线程先启动,并执行run)
Thread.sleep(1000);
t2.start();
/*
输出结果为:
m1....
m2...
*/
}
}
class Processor implements Runnable{
MyClass mc;
Processor(MyClass mc){
this.mc = mc;
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("t1")){
mc.m1();
}
if(Thread.currentThread().getName().equals("t2")){
mc.m2();
}
}
}
class MyClass{
public synchronized void m1(){
//休眠
try {
Thread.sleep(10000);
} catch (Exception e) {}
System.out.println("m1....");
}
/*
//m2方法的执行不需要等待m1的结束,因为m2方法上没有synchronized
public void m2(){
System.out.println("m2...");
}*/
//m2方法会等m1方法结束,t1,t2共享一个mc,并且m1和m2方法上都有synchronized
public synchronized void m2(){
System.out.println("m2...");
}
}
package com.geeklicreed.j2se;
/*
* 类锁,类只有一个,所以如果锁是类级别的,只有一个
*/
public class ThreadTest {
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(new Processor());
Thread t2 = new Thread(new Processor());
t1.setName("t1");
t2.setName("t2");
t1.start();
//延迟,保证t1先执行
Thread.sleep(1000);
t2.start();
/*
输出结果为:
m1...
m2...
*/
}
}
class Processor implements Runnable{
public void run(){
if("t1".equals(Thread.currentThread().getName())){
MyClass.m1();
}
if("t2".equals(Thread.currentThread().getName())){
MyClass.m2();
}
}
}
class MyClass{
//synchronized添加到静态方法上,线程执行到此方法的时候会找类锁
public synchronized static void m1(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {}
System.out.println("m1...");
}
//不会等m1结束,因为该方法没有被synchronized修饰
/*
` public static void m2(){
System.out.println("m2...");
` }
*/
//m2方法会等m1结束之后才能执行,该方法有synchronized
//线程执行该代码需要“类锁”,而类锁只有一个
public synchronized static void m2(){
System.out.println("m2...");
}
}
package com.geeklicreed.j2se;
public class ThreadTest {
public static void main(String[] args) throws Exception {
Object o1 = new Object();
Object o2 = new Object();
Thread t1 = new Thread(new T1(o1, o2));
Thread t2 = new Thread(new T2(o1, o2));
t1.start();
t2.start();
}
}
class T1 implements Runnable {
Object o1;
Object o2;
T1(Object o1, Object o2) {
this.o1 = o1;
this.o2 = o2;
}
@Override
public void run() {
synchronized (o1) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
synchronized (o2) {
}
}
}
}
class T2 implements Runnable {
Object o1;
Object o2;
T2(Object o1, Object o2) {
this.o1 = o1;
this.o2 = o2;
}
@Override
public void run() {
synchronized (o2) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
synchronized (o1) {
}
}
}
}
package com.geeklicreed.j2se;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) throws ParseException {
//1、创建定时器
Timer t = new Timer();
//2、指定定时任务
t.schedule(new LogTimerTack(), new SimpleDateFormat("yyy-MM-dd HH:mm:ss SSS").parse("2017-11-03 17:13:00 000"),
1000*60*60*24);
//打印结果为:
//2017-11-03 17:13:00 009
}
}
//指定任务
class LogTimerTack extends TimerTask{
@Override
public void run() {
System.out.println(new SimpleDateFormat("yyy-MM-dd HH:mm:ss SSS").format(new Date()));
}
}
11、Object类中的wait()方法和notify()方法:
转载于:https://blog.51cto.com/12402717/2045989